iOS之NSURLSession断点下载

之前简单说了一些 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];
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值