关于NSURLSessionde概念的介绍可以参见http://blog.csdn.net/majiakun1/article/details/38133433
在模拟器上测试发现这些下载方式在锁屏或者挂起时也可以下载
普通下载:
都是在viewController里面测试的,定义currentSession的和下载任务downTask这两个属性,使用<NSURLSessionDownloadDelegate>代理方法
为了方便测试 URL是自己搭的服务器上的内容
如果要实现多任务下载 就定义多个task,多个task会同时下载 不同的task用taskIdentifiler进行区分,taskIdentifiler为只读属性,不能赋值,由系统分配其ID值
NSURLRequest *request=[[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"http://192.168.23.1/test/Backkom.mp4"]]; NSURLSessionConfiguration *epheSession=[NSURLSessionConfiguration ephemeralSessionConfiguration]; epheSession.discretionary=YES; self.currentSession=[NSURLSession sessionWithConfiguration:epheSession delegate:self delegateQueue:nil]; self.downTask=[self.currentSession downloadTaskWithRequest:request]; [self.downTask resume];
如果用这种的方式创建task则不会执行NSURLSessionDownloadDelegate中的一些重要的代理方法代理方法,不管成功与否是直接里面的block
self.downTask=[self.currentSession downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error){ NSLog(@"________"); }];
以下就是NSURLSessionDownloadDelegate中得代理方法,需要注意的时把下载的temp文件转存下来需要自己需要指定文件名和类型;另外注意为指定路径时URL初始化用此方法fileURLWithPath,用URLWithString会造成路径错误
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ //下载成功调用此方法, NSFileManager *fileManager = [NSFileManager defaultManager];//文件管理 NSURL *documentsDirectory=[NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingString:@"/Documents/"]]; NSURL *destinationPath = [documentsDirectory URLByAppendingPathComponent:@"Backkom.mp4"]; NSError *error; [fileManager removeItemAtURL:destinationPath error:NULL];//确保文件不在 BOOL success = [fileManager copyItemAtURL:location toURL:destinationPath error:&error]; if(success){ NSLog(@"success path:%@",destinationPath); }else{ NSLog(@"error:%@",error); } }
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ //失败和成功都会调用 if(error){ NSLog(@"error:%@",error); } }
执行下载有数据写入执行,bytesWritten--每次写入的data字节数;totalBytesWritten--当前一共写入的data字节数,totalBytesExpectedToWrite--期望收到的所有data字节数
prograss就是下载进度
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{ double prograss=totalBytesWritten/(double)totalBytesExpectedToWrite; }
如要取消下载可以设置downTask cancel就可以了。
断点续传:
此方式需要定义一个NSData *partialData来存储暂停时需要保存的下载数据,resumableTask为NSURLSessionDownloadTask,当取消下载时,需在cancelByProducingResumeData的block中对已经下载的数据进行保存
if(self.resumableTask){ [self.resumableTask cancelByProducingResumeData:^(NSData *resumeData){ self.partialData=resumeData; }]; }
创建下载时同样使用的时代理方法,注意判断partiaData,不是nil表示已经取消过下载。代理方法里面的代码和上面普通下载一样
if(!self.resumableTask){ NSURLSessionConfiguration *defaultSession=[NSURLSessionConfiguration defaultSessionConfiguration]; defaultSession.discretionary=YES; self.resumeSession=[NSURLSession sessionWithConfiguration:defaultSession delegate:self delegateQueue:nil]; } if(self.partialData){ self.resumableTask=[self.resumeSession downloadTaskWithResumeData:self.partialData]; }else{ NSURLRequest *request=[[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"http://192.168.23.1/test/Backkom.mp4"]]; self.resumableTask=[self.resumeSession downloadTaskWithRequest:request]; } [self.resumableTask resume];
后台下载:
后台下载是在说在程序锁屏,挂起也可以下载,甚至在程序退出时都可以继续下载,是由系统来处理的。在找的demo程序我退出程序都不能下载,看backgroundSessionConfigurationWithIdentifier的文档If the user terminates the app from the multitasking screen, the system cancels all of the session’s background transfers说用户终止应用就会取消session的后台就传输,找了个demo(http://www.cocoachina.com/bbs/read.php?tid=171978)也没有实现程序退出后下载成功,希望有成功的同学能分享下或者指教下。