目录
1、实现原理
2、初始化临时保存路径
3、开始下载
4、暂停
5、继续下载
6、需要用到的代理
7、优缺点
8、总结
1、实现原理
利用NSURLSessionDownloadTask进行下载,通过代理获取实时下载进度并通过UIProgressView显示出来,在暂停时将已下载文件保存下来,在继续下载时从已下载文件开始下载。
效果图
2、初始化临时保存路径
self.mPathStr = @"1.tmp";
首先初始化.tmp为后缀的文件路径名。
3、开始下载
// 开始下载
- (void)start
{
NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"1"];
configuration.allowsCellularAccess = NO; // 允许4G下载
self.mSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
// 从临时路径中获取已下载文件
NSString * path = [NSTemporaryDirectory() stringByAppendingPathComponent:self.mPathStr];
self.mDownloadData = [NSData dataWithContentsOfFile:path];
if (self.mDownloadData.length>0) {
// 继续下载
[self goonDownloadData];
return;
}
// 开始下载
NSString * str1 = @"http://www.ytmp3.cn/down/49055.mp3";
self.mDownloadTask = [self.mSession downloadTaskWithURL:[NSURL URLWithString:str1]];
[self.mDownloadTask resume];
}
NSURLSessionConfiguration在初始化的时候,可以用 [NSURLSessionConfiguration defaultSessionConfiguration] 即默认模式初始化,不过在下载时我们可以用 [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"1"] 来初始化,这个方法通过给定Identifier可以实现后台下载,
在开始方法中先判断临时路径是否已有下载文件,如果已有下载文件则执行继续下载方法,如果下载文件为空则从0开始下载。
4、暂停
// 暂停
-(void)pause
{
[self.mDownloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.mDownloadData = resumeData;
NSString * path = [NSTemporaryDirectory() stringByAppendingPathComponent:self.mPathStr];
[self.mDownloadData writeToFile:path atomically:YES];
self.mDownloadTask = nil;
}];
}
暂停通过 cancelByProducingResumeData 方法实现,该方法提供当前下载文件data,将此文件保存到临时路径以便后续继续下载。
5、继续下载
// 继续
-(void)goonDownloadData
{
NSString * path = [NSTemporaryDirectory() stringByAppendingPathComponent:self.mPathStr];
NSLog(@"path - %@",path);
self.mDownloadData = [NSData dataWithContentsOfFile:path];
self.mDownloadTask = [self.mSession downloadTaskWithResumeData:self.mDownloadData];
[self.mDownloadTask resume];
self.mDownloadData = nil;
}
在继续下载方法中通过 downloadTaskWithResumeData 方法将临时路径中的下载文件作为重新开始下载的初始文件。
6、需要用到的代理
1)
/**
下载时调用,可以实时监听下载的进度
@param session
@param downloadTask
@param bytesWritten 本次下载的文件大小
@param totalBytesWritten 已经下载的数据大小
@param totalBytesExpectedToWrite 总大小
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
float process = totalBytesWritten * 1.0 / totalBytesExpectedToWrite;
NSLog(@"process -- %f -- ",process);
dispatch_async(dispatch_get_main_queue(), ^{
self.mProgressView.progress = process;
self.mLabel.text = [NSString stringWithFormat:@"%.2f",process];
});
}
此代理方法会调用很多次,可以实时获取下载进度,并且获取本次下载文件大小
2)
/**
恢复下载时调用
@param session
@param downloadTask
@param fileOffset 恢复下载时开始下载位置(已下载文件大小)
@param expectedTotalBytes 总大小
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
float process = fileOffset * 1.0 / expectedTotalBytes;
NSLog(@"process -- %f -- ",process);
dispatch_async(dispatch_get_main_queue(), ^{
self.mProgressView.progress = process;
self.mLabel.text = [NSString stringWithFormat:@"%.2f",process];
});
}
此方法为恢复下载时调用,可以获取之前已下载数据大小和文件总大小,可以用于显示默认进度条,不写也没影响
3)
// 下载完成,location 临时文件地址
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@" --默认地址:location - %@ -- ",location);
NSString * path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
path = [path stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL URLWithString:path] error:nil];
NSLog(@" --转移地址:path - %@ -- ",path);
}
此方法为下载完成方法,可以获取下载完成的临时文件路径location:以CFNetworkDownload开头,.tmp为后缀的路径。可以将文件转移到特定的文件路径,方便后续使用。
7、优缺点
优点:实现方便快捷,可以应对一般的断点续传或者短时的后台下载。
缺点:不足之处是不能实现离线下载,或者长时间的后台下载。如果在实现后台下载时,后台自动杀死或者人为杀掉进程,不能实时保存已下载的文件,因此在重启进程时不能获取之前已下载的文件来进行继续下载。
当然我们可以在实时获取下载进度的方法进行保存,但这样实时的保存操作特别耗费资源,因此并不推荐。
8、总结
通过 NSURLSessionDownloadTask 实现断点续传及下载很方便,可以满足大部分功能。
如果需要后台离线下载还是需要用 NSURLSessionDataTask 实现,具体实现方法后续添加。