这篇文章讲的是NSURLSessionDownloadTask
DownloadTask
和DataTask
的区别:
DownloadTask
是把文件直接download到磁盘,详细来说,有以下几点区别:
- DownloadTask支持BackgroundSession,而dataTask不支持
- DownloadTask支持断点续传(下载到一半的时候暂停,重启后继续下载,前提下载的服务器支持断点续传)
如何处理DownloadTask?
一.用Block的方式来处理DownloadTask
这种情况下和DataTask类似,处理起来比较简单,但是不灵活。
其中,Location
是所下载的临时文件存储的路径
self.downloadTask = [self.session downloadTaskWithURL:(NSURL *) completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { }];
继续上一次保存的数据下载:
self.downloadTask = [self.session downloadTaskWithResumeData:(NSData *) completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { }]
上面的ResumeData是通过
[self.downloadTask cancelByProducingResumeData:^(NSData *resumeData)completionHandler]
或者通过在Session的代理函数的Error
中存储,Key是NSURLSessionDownloadTaskResumeData
:
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
二.用代理的方式处理
除了NSURLSessionDelegate
用来处理Session层次的事件,NSURLSessionTaskDelegate
处理Task的共性事件之外,还有NSURLSessionDownloadTaskDelegate
用来特别处理Download事件。
1.每次在用上文中的ResumeData创建DownloadTask之后,然后让task开始执行,这个函数就会调用。
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffsetexpectedTotalBytes:(int64_t)expectedTotalBytes
2.下载的进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWrittentotalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
3.下载完成的事件
注意,一定要在这个函数返回之前,对数据进行使用,或者保存
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTaskdidFinishDownloadingToURL:(NSURL *)location
代码展示:
@interface DownloadTaskViewController()<NSURLSessionDelegate,NSURLSessionTaskDelegate,NSURLSessionDownloadDelegate,UITextFieldDelegate>
@property (strong,nonatomic)NSURLSession * session;
@property (strong,nonatomic)NSURLSessionDownloadTask * downloadTask;
@property (weak, nonatomic) IBOutlet UITextField *urltextfield;
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@property (weak, nonatomic) IBOutlet UIProgressView *progressview;
@end
@implementation DownloadTaskViewController//开始下载
- (IBAction)download:(id)sender { self.progressview.hidden = NO; self.progressview.progress = 0.0;
NSString * imageurl = self.urltextfield.text; self.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:imageurl]]; [self.downloadTask resume];
[self.session finishTasksAndInvalidate];}//初始化
-(void)viewDidLoad{
self.urltextfield.delegate = self; NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"id"];
self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}//Session层次的Task完成的事件
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if (error) {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
}
self.progressview.hidden = YES;}
//Task完成的事件
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
NSData * data = [NSData dataWithContentsOfURL:location.filePathURL]; UIImage * image = [UIImage imageWithData:data]; self.imageview.image = image; UIImageWriteToSavedPhotosAlbum(image, nil,nil,nil); self.session = nil;
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{}
//下载进度的代理
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
if (totalBytesExpectedToWrite != NSURLSessionTransferSizeUnknown) { self.progressview.progress = totalBytesWritten/(float)totalBytesExpectedToWrite; }}
//TextField Delegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField{ [self.urltextfield resignFirstResponder];
return YES;}
@end