使用NSURLConnection进行大文件下载

使用NSURLConnection进行大文件下载


  • 内存管理

    • sendSynchronousRequest:returningResponse:error:(同步下载),内存占用过多,阻塞(主)线程。
    • sendAsynchronousRequest:queue:completionHandler:(异步下载),内存占用过多。

  • 下载任务所在线程&代理方法所在线程

    • NSURLConenction下载任务默认被添加至当前线程run loopdefault mode下。所以,它可以作为一个事件源来开启子线程上的运行循环。

    • 默认,代理方法下载任务同一个线程

    • setDelegateQueue:方法有两个作用:

      • 设置代理方法所在的线程。
      • 设置下载任务所在的线程。注意,必须在下载任务开始之前设置,否则无效。
          /*
           在子线程上创建NSURLConnection,然后开启运行循环,
           以使得connection的下载任务被正确执行
           */
          NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:mRequest delegate:self]; // connection一经创建立即开始数据载入
          [connection setDelegateQueue:[NSOperationQueue new]]; // 只能设置代理方法的线程
          CFRunLoopRun();
      
    • 暂缓下载任务,使用setDelegateQueue方法同时配置下载任务和代理方法的线程,然后start,可以使得免去手动创建线程开启run loop的痛苦。

          /*
          利用setDelegateQueue将下载任务和代理方法都转移至子线程,
          效果同上面的代码块一样
           */
          NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:mRequest delegate:self startImmediately:NO]; // 暂缓数据载入
          [connection setDelegateQueue:[NSOperationQueue new]]; // 同时设置代理方法和下载任务的线程
          [connection start]; // 手动开启connection
          
      

  • NSURLConnectionDownloadDelegateNSURLConnectionDataDelegate之间只能选用一套。同时实现,只有一套代理方法会被调用,一般使用后者。

  • NSURLConnectionDownloadDelegate
    • connectionDidFinishDownloading:destinationURL:有bug,下载后找不到文件。

  • NSURLConnectionDataDelegate
    • NSFileManager负责管理文件系统,利用它来获取文件尺寸信息
    • NSFileHandle操作一个文件内部的读写,利用它来实现文件的断点续传。需要手动创建待操作的文件。
    • NSOutputStream以输入流的形式向文件写入字符,效果和file handle一样。不需要手动创建待创建的文件。

  • 文件下载的逻辑

    localFileLength // 本地文件长度
    expectedFileLength // 服务器端文件长度(通过HEAD方法 + NSURLConnection的同步请求获取)
    
    if (localFileLength == 0) {
        // 从头下载文件
    } else if (localFileLength < expectedFileLength) {
        // 文件部分存在,断点续传
    } else if (localFileLength > expectedFileLength) {
        // 文件下载冗余,删除重新下载
    } else if (localFileLength == expectedFileLength) {
        // 文件已经存在,不用下载
    }
    
    

你可能感兴趣的:(使用NSURLConnection进行大文件下载)