这里介绍NSURLSessionDownloadTask的两种下载文件的方式.一种是block形式的,代码精简,但是无法控制下载进度,以及断点下载.
第二种是delegate的形式,功能强大,既可以控制下载进度,又可以设置断点下载.
在项目中 大家可以根据需要选择最佳的实践方案:
1.NSURLSessionDownloadTask的block形式.
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler
downloadTaskWithURL
: 该方法默认已经实现了边下载边写入
.所以在 completionHandler 这个 block 里,我们需要把文件从一个临时地址移动到一个永久的地址保存起来.通过指定 completionHandler 这个 block 将创建一个隐式的 delegate
,来替代该 task 原来的 delegate——session。
参数解释:
第一个参数: 需要下载的文件的路径
第二个参数:
- location: 下载好的文件在手机磁盘上的位置,临时存储
- response: 响应头
- error: 请求是否有错
其他两种block形式分别根据url,还有恢复数据来创建相应的
NSURLSessionDownloadTask.如下所示:
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler
下面是一个下载image的实例,然后把image移动
// 1.创建NSURLSession
NSURLSession *session = [NSURLSession sharedSession];
// 2.创建Task
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSString *dir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 1.生成需要移动到得路径
NSString *toPath = [dir stringByAppendingPathComponent:[response.suggestedFilename lastPathComponent]];
NSLog(@"%@",toPath);
// 2.移动文件
NSFileManager *manager = [NSFileManager defaultManager];
[manager moveItemAtURL:location toURL:[NSURL fileURLWithPath:toPath] error:nil];
}];
// 3.启动任务
[task resume];
2.使用delegate进行下载
#import "ViewController.h"
@interface ViewController ()<NSURLSessionDownloadDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
- (IBAction)startBtnClick:(UIButton *)sender;
- (IBAction)pauseBtnClick:(UIButton *)sender;
- (IBAction)goOnBtnClick:(UIButton *)sender;
/** 任务 */
@property (nonatomic, strong) NSURLSessionDownloadTask *task;
/** session */
@property (nonatomic, strong) NSURLSession *session;
/** 恢复信息 */
@property (nonatomic, strong) NSData *resumeData;
@end
@implementation ViewController
- (IBAction)startBtnClick:(UIButton *)sender {
// 1.创建NSURLSession
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
self.session = session;
// 2.创建Task
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
self.task = [session downloadTaskWithURL:url];
// 3.启动任务
[self.task resume];
}
- (IBAction)pauseBtnClick:(UIButton *)sender
{
// resumeData : 保存了当前用户下载的信息
// 只要有了这些信息, 以后就可以通过这些信息恢复下载
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
self.resumeData = resumeData;
}];
}
- (IBAction)goOnBtnClick:(UIButton *)sender
{
self.task = [self.session downloadTaskWithResumeData:self.resumeData];
[self.task resume];
}
#pragma mark - NSURLSessionDownloadDelegate
/*
1.接收到服务器返回的数据
正在写入数据
bytesWritten: 当前这一次写入的数据大小
totalBytesWritten: 已经写入到本地文件的总大小
totalBytesExpectedToWrite : 被下载文件的总大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
self.progressView.progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;
}
/*
2.恢复下载时调用
fileOffset : 恢复之后要从文件的什么地方开始写入数据
expectedTotalBytes: 文件总共需要下载的大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
NSLog(@"fileOffset = %lld, expectedTotalBytes = %lld", fileOffset, expectedTotalBytes);
}
//3.下载完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
// 1.生成需要移动到得路径
NSString *dir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *toPath = [dir stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
// 2.移动文件
NSFileManager *manager = [NSFileManager defaultManager];
[manager moveItemAtURL:location toURL:[NSURL fileURLWithPath:toPath] error:nil];
}
//4.请求完毕,如果有错误, 那么error有值
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"didCompleteWithError");
}
@end