NSURLSession下载文件—断点续传

40 篇文章 0 订阅
17 篇文章 0 订阅
  • 首先我们懒加载一下:NSURLSession

  • 会话配置对象

  • 大多情况使用默认的配置就可以了
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
  • NSOperationQueue:没有串行的概念
  • delegateQueue:传入nil和[[NSOperationQueue alloc] init]效果是一样的。并发执行代理方法
  • delegateQueue:传人[NSOperationQueue mainQueue],在主线程执行代理方法,不会阻塞主线程处理其他事件。
  • 如何选择队列
    • 如果代理方法中要更新UI/不做耗时操作,则选择主队列,其他都选择自定义队列
    • session会对代理进行强引用,直到app退出或者显示销毁会话对象
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
- (NSURLSession *)session
{
    if (_session == nil)
    {
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}

完成了懒加载。


写一个方法,根据文件url获得续传数据保存的路径

- (NSString *)resumeDataPath:(NSURL *)url{
    // 获得保存续传数据的文件名字
    NSString *fileName = [NSString stringWithFormat:@"%@~resume",url.absoluteString.md5String];
    // 获得全路径
    NSString *resumePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
    NSLog(@"保存续传数据的路径 = %@",resumePath);
    return resumePath;
}

根据url加载续传数据

/**
 *  根据url加载续传数据
 */
- (NSData *)loadResumeData:(NSURL *)url{
    // 获得续传数据保存的路径
    NSString *filePath = [self resumeDataPath:url];
    return [NSData dataWithContentsOfFile:filePath];
}

点击开始按钮

/**
 *  开始下载
 */
- (IBAction)start {
      NSURL *url = [NSURL URLWithString:@"http://localhost/abc.mp4"];
    self.url = url;
    // 从沙盒中加载续传数据
    self.resumeData = [self loadResumeData:self.url];
    if (self.resumeData == nil) { // 没有续传数据
        // 使用代理,就不能使用全局session
        // 一旦提供了 completionHandler 回调,代理方法不会被触发。
        self.downloadTask = [self.session downloadTaskWithURL:url];
    } else {    // 有续传数据
        // 根据续传数据发起下载任务,那么任务的下载就从续传数据指定的位置开始下载
        self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    }
    // 继续任务
    [self.downloadTask resume];
}

暂停下载

/**
 *  暂停下载
 */
- (IBAction)pause {
    // resumeData:续传数据,本质一个plist文件
    [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
         NSLog(@"暂停下载 = %zd",resumeData.length);
        // 记录续传数据
        self.resumeData = resumeData;

        // 清空下载任务
        self.downloadTask = nil;
        // 将续传数据写入文件中
        [resumeData writeToFile:[self resumeDataPath:self.url] atomically:YES];
    }];
}

继续下载

- (IBAction)resume {
    if (self.resumeData == nil) {
        NSLog(@"没有续传数据");
        return;
    }
    // 根据续传数据发起下载任务,那么任务的下载就从续传数据指定的位置开始下载
    self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];

    // 继续任务
    [self.downloadTask resume];
}

NSURLSessionDownloadDelegate 代理方法

/**
 *  下载完成回调 -- 必须实现
 *
 *  @param session      会话
 *  @param downloadTask 下载任务
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSLog(@"下载完成 = %@",location);

    // 当任务执行完成后销毁会话
    [self.session finishTasksAndInvalidate];
    self.session = nil;
}

进度可以在这个方法中得到:

/**
 *  @param bytesWritten              本次下载的字节数
 *  @param totalBytesWritten         已经下载的字节数
 *  @param totalBytesExpectedToWrite 文件总字节数
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    // 计算进度
    CGFloat progress = (CGFloat)totalBytesWritten / totalBytesExpectedToWrite;
    NSLog(@"%f",progress);
    self.progressView.progress = progress;

}

这个方法,没什么用

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
    NSLog(@"%s",__FUNCTION__);
}

自此,就完成了文件的下载,做到了内存以及断点续传

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值