之前简单说了一些
NSURLSession
的用法和介绍
简单的断点下载
NSURLSession
提供几个方法用于开始(resume)
,暂停(suspend)
,取消(cancel)
请求- 其中
取消
分为2种,不可恢复取消 cancel
,和可恢复取消 cancelByProducingResumeData
- 其中
开始下载
//创建URL
NSString *urlStr = @"http://localhost/video.mp4";
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//创建回话
NSURLSessionConfiguration *def = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:def delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDownloadTask *loadTask = [session downloadTaskWithRequest:request];
[loadTask resume];
//定义属性 保存
self.loadTask = loadTask;
self.session = session;
暂停下载
- (IBAction)handleSuppendAction:(UIButton *)sender {
NSLog(@"-----暂停下载");
[self.loadTask suspend];
}
取消下载
- `ResumeData可恢复的现在数据
///取消下载
- (IBAction)handleCancaleAction:(UIButton *)sender {
NSLog(@"-------取消下载");
//调用这个取消下载不可以在恢复
// [self.loadTask cancel];
//调用这个取消下载可以在恢复 下载 不过要重新开启一个session
[self.loadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.resumeData = resumeData;
}];
}
恢复下载
///回复下载
- (IBAction)handleAssignStartAction:(UIButton *)sender {
NSLog(@"------回复下载");
if (self.resumeData) {
//重开始终端的地方下载
self.loadTask = [self.session downloadTaskWithResumeData:self.resumeData];
}
[self.loadTask resume];
}
代理方法
- (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;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
//
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
//获取下载文件的名称
NSString *name = downloadTask.response.suggestedFilename;
//全路径
NSString *fullpath = [path stringByAppendingPathComponent:name];
NSFileManager *manager = [NSFileManager defaultManager];
[manager moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullpath] error:nil];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
}
在日常开发中 我们一般不使用
NSURLSessionDownloadTask
下载,因为如果用户退出程序的话,在此下载的时候比较复杂,一般使用的上NSURLSessionDataTask
NSURLSessionDataTask
实现断点下载
声明 属性 用来存储
@interface ViewController ()<NSURLSessionDataDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *proessView;
/** 接受响应体信息 */
@property (nonatomic, strong) NSFileHandle *handle;
@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, assign) NSInteger currentSize;
@property (nonatomic, strong) NSString *fullPath;
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
@property (nonatomic, strong) NSURLSession *session;
@end
代码实现
//懒加载路径
-(NSString *)fullPath
{
if (_fullPath == nil) {
//获得文件全路径 拼接文件名时 最好声明宏
_fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"100.mp4"];
}
return _fullPath;
}
// 懒加载回话对象 --- 记得一定要释放这个对象
-(NSURLSession *)session
{
if (_session == nil) {
//3.创建会话对象,设置代理
/*
第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
第二个参数:代理
第三个参数:设置代理方法在哪个线程中调用
*/
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
//懒加载 下载任务
-(NSURLSessionDataTask *)dataTask
{
if (_dataTask == nil) {
//1.url
NSURL *url = [NSURL URLWithString:@"http://localhost/video.mp4"];
//2.创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//3 设置请求头信息,告诉服务器请求那一部分数据
self.currentSize = [self getFileSize];
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
[request setValue:range forHTTPHeaderField:@"Range"];
//4.创建Task
_dataTask = [self.session dataTaskWithRequest:request];
}
return _dataTask;
}
//离线是 获取 本地的数据大小
-(NSInteger)getFileSize
{
//获得指定文件路径对应文件的数据大小
NSDictionary *fileInfoDict = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];
NSLog(@"%@",fileInfoDict);
NSInteger currentSize = [fileInfoDict[@"NSFileSize"] integerValue];
return currentSize;
}
功能方法
//开始下载
- (IBAction)startBtnClick:(id)sender
{
[self.dataTask resume];
}
//暂停下载
- (IBAction)suspendBtnClick:(id)sender
{
NSLog(@"_________________________suspend");
[self.dataTask suspend];
}
//注意:dataTask的取消是不可以恢复的
- (IBAction)cancelBtnClick:(id)sender
{
NSLog(@"_________________________cancel");
[self.dataTask cancel];
self.dataTask = nil;
}
//回复现在
- (IBAction)goOnBtnClick:(id)sender
{
NSLog(@"_________________________resume");
[self.dataTask resume];
}
代理方法
/**
* 1.接收到服务器的响应 它默认会取消该请求
*
* @param session 会话对象
* @param dataTask 请求任务
* @param response 响应头信息
* @param completionHandler 回调 传给系统
*/
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
//获得文件的总大小
//expectedContentLength 本次请求的数据大小
self.totalSize = response.expectedContentLength + self.currentSize;
if (self.currentSize == 0) {
//创建空的文件
[[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];
}
//创建文件句柄
self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
//移动指针
[self.handle seekToEndOfFile];
/*
NSURLSessionResponseCancel = 0,取消 默认
NSURLSessionResponseAllow = 1, 接收
NSURLSessionResponseBecomeDownload = 2, 变成下载任务
NSURLSessionResponseBecomeStream 变成流
*/
completionHandler(NSURLSessionResponseAllow);
}
/**
* 接收到服务器返回的数据 调用多次
*
* @param session 会话对象
* @param dataTask 请求任务
* @param data 本次下载的数据
*/
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
//写入数据到文件
[self.handle writeData:data];
//计算文件的下载进度
self.currentSize += data.length;
NSLog(@"%f",1.0 * self.currentSize / self.totalSize);
self.proessView.progress = 1.0 * self.currentSize / self.totalSize;
}
/**
* 请求结束或者是失败的时候调用
*
* @param session 会话对象
* @param dataTask 请求任务
* @param error 错误信息
*/
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"%@",self.fullPath);
//关闭文件句柄
[self.handle closeFile];
self.handle = nil;
}
-(void)dealloc
{
//清理工作
//finishTasksAndInvalidate
[self.session invalidateAndCancel];
}