本篇简述一下实现文件下载功能,包含大文件下载,后台下载,杀死进程,重新启动时继续下载,设置下载并发数,监听网络改变等,并在最后附有Demo。
下载功能的实现:
使用的网络连接的类为NSURLSession。该类用以替代NSURLConnection,在iOS7时推出,至此iOS系统才有了后台传输。在初始化NSURLSession前,需要先创建NSURLSessionConfiguration,可以理解为是NSURLSession需要的一个配置。NSURLSessionConfiguration有三种模式:
1. default:可以使用缓存的Cache、Cookie、鉴权。
2. ephemeral,仅内存缓存,不使用缓存的Cache、Cookie、鉴权。
3. background,支持后台传输,需要一个identifier标识,用来重新连接session对象。
创建后台模式NSURLSessionConfiguration:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"HWDownloadBackgroundSessionIdentifier"];
创建NSURLSession,设置配信息、代理、代理线程:
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
在实现下载前,还需要了解一个很重要的类,NSURLSessionTask,无论下载多少文件,我们只需要初始化一个NSURLSession即可,而每个task对应一个任务,需要通过task才能实现下载,NSURLSessionTask是一个基类,有四个子类:
1. NSURLSessionDataTask:下载时,内容以NSData对象返回,需要我们不断写入文件,但不支持后台传输,切换后台会终止下载,回到前台时在协议方法中输出error,下面贴一下用NSURLSessionDataTask实现断点续传的核心代码:
// 遵守协议
<NSURLSessionDataDelegate>
// 创建NSMutableURLRequest
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setValue:[NSString stringWithFormat:@"bytes=%zd-", tmpFileSize] forHTTPHeaderField:@"Range"];
// 创建NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
// 开始、继续下载
[dataTask resume];
// 暂停下载
[dataTask suspend];
// 取消下载
[dataTask cancel];
// 接收到服务器响应
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
// 更新文件的总大小
totalFileSize = response.expectedContentLength + tmpFileSize;
// 创建输出流
NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:fullPath append:YES];
[stream open];
// 允许处理服务器的响应,继续接收数据
completionHandler(NSURLSessionResponseAllow);
}
// 接收到服务器返回数据,会被调用多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
// 写入数据
[stre