使用NSURLConnection进行大文件下载
-
内存管理
-
sendSynchronousRequest:returningResponse:error:
(同步下载),内存占用过多,阻塞(主)线程。 -
sendAsynchronousRequest:queue:completionHandler:
(异步下载),内存占用过多。
-
-
下载任务
所在线程&代理方法
所在线程NSURLConenction
的下载任务
默认被添加至当前线程run loop
的default 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
-
NSURLConnectionDownloadDelegate
和NSURLConnectionDataDelegate
之间只能选用一套。同时实现,只有一套代理方法会被调用,一般使用后者。
-
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) { // 文件已经存在,不用下载 }