使用NSURLConnection進(jìn)行大文件下載
-
內(nèi)存管理
-
sendSynchronousRequest:returningResponse:error:
(同步下載)噪叙,內(nèi)存占用過(guò)多,阻塞(主)線程寥闪。 -
sendAsynchronousRequest:queue:completionHandler:
(異步下載)琼懊,內(nèi)存占用過(guò)多价认。
-
-
下載任務(wù)
所在線程&代理方法
所在線程NSURLConenction
的下載任務(wù)
默認(rèn)被添加至當(dāng)前線程run loop
的default mode
下。所以,它可以作為一個(gè)事件源來(lái)開(kāi)啟子線程上的運(yùn)行循環(huán)涉枫。默認(rèn)探越,
代理方法
和下載任務(wù)
在同一個(gè)線程
狡赐。-
setDelegateQueue:
方法有兩個(gè)作用:- 設(shè)置
代理方法
所在的線程。 - 設(shè)置
下載任務(wù)
所在的線程钦幔。注意枕屉,必須在下載任務(wù)開(kāi)始之前設(shè)置,否則無(wú)效鲤氢。
/* 在子線程上創(chuàng)建NSURLConnection搀擂,然后開(kāi)啟運(yùn)行循環(huán)西潘, 以使得connection的下載任務(wù)被正確執(zhí)行 */ NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:mRequest delegate:self]; // connection一經(jīng)創(chuàng)建立即開(kāi)始數(shù)據(jù)載入 [connection setDelegateQueue:[NSOperationQueue new]]; // 只能設(shè)置代理方法的線程 CFRunLoopRun();
- 設(shè)置
-
暫緩下載任務(wù),使用
setDelegateQueue
方法同時(shí)配置下載任務(wù)和代理方法的線程哨颂,然后start
喷市,可以使得免去手動(dòng)創(chuàng)建線程
和開(kāi)啟run loop
的痛苦。/* 利用setDelegateQueue將下載任務(wù)和代理方法都轉(zhuǎn)移至子線程威恼, 效果同上面的代碼塊一樣 */ NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:mRequest delegate:self startImmediately:NO]; // 暫緩數(shù)據(jù)載入 [connection setDelegateQueue:[NSOperationQueue new]]; // 同時(shí)設(shè)置代理方法和下載任務(wù)的線程 [connection start]; // 手動(dòng)開(kāi)啟connection
-
NSURLConnectionDownloadDelegate
和NSURLConnectionDataDelegate
之間只能選用一套品姓。同時(shí)實(shí)現(xiàn),只有一套代理方法會(huì)被調(diào)用箫措,一般使用后者缭黔。
-
NSURLConnectionDownloadDelegate
-
connectionDidFinishDownloading:destinationURL:
有bug,下載后找不到文件蒂破。
-
-
NSURLConnectionDataDelegate
-
NSFileManager
負(fù)責(zé)管理文件系統(tǒng)馏谨,利用它來(lái)獲取文件尺寸信息
。 -
NSFileHandle
操作一個(gè)文件內(nèi)部的讀寫(xiě)附迷,利用它來(lái)實(shí)現(xiàn)文件的斷點(diǎn)續(xù)傳惧互。需要
手動(dòng)創(chuàng)建待操作的文件。 -
NSOutputStream
以輸入流的形式向文件寫(xiě)入字符喇伯,效果和file handle一樣喊儡。不需要
手動(dòng)創(chuàng)建待創(chuàng)建的文件。
-
-
文件下載的邏輯
localFileLength // 本地文件長(zhǎng)度 expectedFileLength // 服務(wù)器端文件長(zhǎng)度(通過(guò)HEAD方法 + NSURLConnection的同步請(qǐng)求獲鹊揪荨) if (localFileLength == 0) { // 從頭下載文件 } else if (localFileLength < expectedFileLength) { // 文件部分存在艾猜,斷點(diǎn)續(xù)傳 } else if (localFileLength > expectedFileLength) { // 文件下載冗余,刪除重新下載 } else if (localFileLength == expectedFileLength) { // 文件已經(jīng)存在捻悯,不用下載 }