美文网首页
URLSession 断点续传

URLSession 断点续传

作者: 玉松 | 来源:发表于2016-07-14 14:46 被阅读92次

    关于NSURLSession的断点续传的特点:
    在运行的时候,能够暂停和继续,但是一旦退出,就没有办法在继续,需要重新下载!

    @interface ViewController () <NSURLSessionDownloadDelegate>

    /** 全局网络会话 - 管理所有的网络请求 */

      @property (nonatomic, strong) NSURLSession *session;
    
    @property (weak, nonatomic) IBOutlet UIProgressView *progressView;
    
    // 下载任务
    @property (nonatomic, strong)         NSURLSessionDownloadTask *downloadTask;
    // 续传数据
    @property (nonatomic, strong) NSData *resumeData;
    

    @end

    @implementation ViewController

    // 开始下载
    - (IBAction)start {
    // 1. url
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/123.mp4"];

    // 2. 开始下载
    self.downloadTask = [self.session downloadTaskWithURL:url];
    [self.downloadTask resume];
    

    }

    // 暂停下载

    - (IBAction)pause {
    NSLog(@"暂停");
    
    // 一旦暂停,就不需要再次被暂停,否则 resumeData 就是 nil
    // 在 OC 中,可以在运行时给nil发送任何消息,但是不会执行,也不会报错!
    [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
        NSLog(@"%tu", resumeData.length);
        
        // 保存续传数据
        self.resumeData = resumeData;
        
        // 释放下载任务,防止被再次暂停
        self.downloadTask = nil;
    }];}
    

    // 继续下载

    - (IBAction)resume {
    
    // 需要防止下载任务重复被创建!
    if (self.resumeData == nil) {
        NSLog(@"没有续传数据!");
        return; }
    
    // 使用续传数据创建下载任务 - 一旦使用续传数据新建了下载任务,续传就没用了!
    self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    
    [self.downloadTask resume];
    
    // 释放续传数据
    self.resumeData = nil;}
    

    //mark - <NSURLSessionDownloadDelegate>

     // 下载完成 iOS 8.0 必须实现
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSLog(@"!!!%@ %@", location, [NSThread currentThread]);}
    
    // 续传的方法,iOS 7.0 必须实现,在 iOS 8.0 可选
    - (void)URLSession:(NSURLSession *)session   downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
    
    NSLog(@"%s", __FUNCTION__);}
    
      // 进度的方法,iOS 7.0 必须实现,在 iOS 8.0 可选
    /**
     bytesWritten               本次下载字节数
     totalBytesWritten          已经下载字节数
     totalBytesExpectedToWrite  总下载字节数
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    
    float progress = (float) totalBytesWritten / totalBytesExpectedToWrite;
    NSLog(@"%f %@", progress, [NSThread currentThread]);
    
    dispatch_async(dispatch_get_main_queue(), ^{
        self.progressView.progress = progress;
    });}
    

    // MARK: - 懒加载

    - (NSURLSession *)session {
      if (_session == nil) {
        // 会话配置,可以配置全局的网络会话属性:包括:身份验证,访问超时,cookie,安全...
        // 一经设置,全局共享!
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        /**
         代理的工作队列
         
         nil - 异步回调 和 实例化一个 操作队列的效果是一样的!
         [[NSOperationQueue alloc] init] - 异步回调
            - 注意:下载本身的线程"只有一条"
            - 代理回调可以在"多个线程"回调!
         
         [NSOperationQueue mainQueue] - 主队列回调
            提示:
            - 下载本身就是异步执行的,和 NSURLConnection 是一样的
            - 指定代理执行的队列,不会影响到下载本身的执行
            - NSURLSession 即使在主线程回调也不会造成阻塞
         
         如何选择队列?
         - 如果执行完毕后,没有复杂的操作,可以指定主队列,可以不用考虑线程间通讯!
         */
        _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    }
    return _session;}
    

    @end

    相关文章

      网友评论

          本文标题:URLSession 断点续传

          本文链接:https://www.haomeiwen.com/subject/eebejttx.html