1.斷點續(xù)傳
定義:我們有時在邊聊天邊下載大文件時净神,感覺很卡蔫饰,這時可以暫停下載任務(wù)酌呆,聊完天再繼續(xù)下載文件疗锐。這就是斷點下載
實現(xiàn)方式:iOS中利用NSURLSession可以進(jìn)行文件斷點下載坊谁,下面就一起來實現(xiàn)它吧。
知識儲備:1.對NSURLSesiion的認(rèn)識
NSURLSesiion是蘋果在iOS7推出的一個類滑臊,它具備了NSURLConnection所具備的方法口芍,同時也比它更強大。蘋果推出它的目的大有取代NSURLConnection的趨勢或者目的雇卷。
2.NSURLSesiion的作用
實現(xiàn)對文件的下載與上傳鬓椭。在NSURLSesiion中颠猴,任何請求都可以被看做是一個任務(wù)。而NSURLSesiionData有兩個子類:NSURLSessionDownlaodTask實現(xiàn)文件下載和NSURLSessionUploadTask實現(xiàn)文件上傳小染。
3.NSURLSession的獲取
NSURLSession的獲取可以用NSURLSessionDownloadTaskdelegate的方法獲取翘瓮,但是必須得遵循這個協(xié)議。獲取如下:
NSURLSessionDonfiguration*configuration=[NSURLSessionDonfiguration defaultSessionconfiguration];
self.session=[NsURLSessionsessionWithConfiguration:NSURLSessionDonfiguration delegate: self?delegateQueue:[NSOperationQueue mainQueue]];
4.下載任務(wù)的創(chuàng)建
NSURLSessionDownlaodTask* task=[self.sessiondownloadTaskWithURL:url]
5.NSURLSessionDownloadDelegate的代理方法:
它有三個方法:
6.沙盒路徑的獲取
NSString*path=[NSSearchPathForDiretoriesInDomains(NSDocumentDirectoriy,NSUserDomainMask, YES ) ?lastObject];
7.caches路徑的獲取及里面文件名的創(chuàng)建
NSString *caches=[NSSearchPathForDiretoriesInDomains(NSCachesDirectoriy,NSUserDomainMask, YES ) ?lastObject];
NSString* filename=[cachesstringByAppendingPathComponent:downloadTask.response.suggestedname];
第二部分對程序幾個屬性的說明
1.resumeData
該參數(shù)包含了繼續(xù)下載文件的位置信息裤翩。也就是說资盅,當(dāng)你下載了10M得文件數(shù)據(jù),暫停了踊赠。那么你下次繼續(xù)下載的時候是從第10M這個位置開始的呵扛,而不是從文件最開始的位置開始下載。因而為了保存這些信息筐带,所以才定義了這個NSData類型的這個屬性:resumeData
2. ?task
該參數(shù)的類型是NSURLSessionDownloadTask今穿。因為在程序調(diào)用暫停(pause)這個方法時,必須擁有這個屬性伦籍,怎么拿到它了荣赶?最好的辦法就是讓控制器擁有這個屬性。
3. session
該參數(shù)的類型是NSURLSession.在程序調(diào)用繼續(xù)下載(resume)這個方法時鸽斟,必須擁有這個session拔创。因為之前的任務(wù)task被取消了,無法在復(fù)用了富蓄,所以用懶加載的方法剩燥,讓session只創(chuàng)建一次,同時也讓控制器擁有了這個屬性立倍。
*使用NSURLSessionDataTask可以很輕松實現(xiàn)斷點續(xù)傳灭红,可是有個致命的缺點就是無法進(jìn)行后臺下載
二:對NSURLSessionDownloadTask解釋
? ? ? ? 使用NSURLSessionDataTask可以很輕松實現(xiàn)斷點續(xù)傳,可是有個致命的缺點就是無法進(jìn)行后臺下載口注,一點應(yīng)用程序進(jìn)入了后臺变擒,便會停止下載。所以無法滿足我們的需求寝志。而NSURLSessionDownloadTask是唯一可以實現(xiàn)后臺下載的類娇斑,所以我們只能從這個類進(jìn)行下手了。
那么本篇我們就來談?wù)勱P(guān)于應(yīng)用程序隨時可能被殺死的情況下材部,如何進(jìn)行斷點續(xù)傳毫缆。
(一):關(guān)于斷點續(xù)傳原理:
首先,如果想要進(jìn)行斷點續(xù)傳,那么需要簡單了解一下斷點續(xù)傳的工作機制乐导,在HTTP請求頭中苦丁,有一個Range的關(guān)鍵字,通過這個關(guān)鍵字可以告訴服務(wù)器返回哪些數(shù)據(jù)給我物臂。
比如:
bytes=500-999 表示第500-第999字節(jié)
bytes=500- 表示從第500字節(jié)往后的所有字節(jié)
然后我們再根據(jù)服務(wù)器返回的數(shù)據(jù)旺拉,將得到的data數(shù)據(jù)拼接到文件后面,就可以實現(xiàn)斷點續(xù)傳了产上。
(二):關(guān)于文件下載與暫停的分析:
1.當(dāng)使用NSURLSessionDownloadTask進(jìn)行下載的時候,系統(tǒng)會在cache文件夾下創(chuàng)建一個下載的路徑.(路徑下會有一個以"CFNetworking"打頭的.tmp文件(以下簡稱"下載文件"防止混淆),這個就是我們正在下載中的文件)
2.調(diào)用cancelByProducingResumeData:方法后,會得到一個data文件,通過String格式化后蛾狗,發(fā)現(xiàn)是一個XML文件.
3.XML里面包含了關(guān)于.tmp文件的一些關(guān)鍵點的描述,包括"Range","key","下載文件的路徑"等等.而原本存在于download文件下的下載文件蒂秘,則被移動到了系統(tǒng)tmp文件夾目錄下.
4.當(dāng)我們再次進(jìn)行resume操作的時候,下載文件則又被移回到了download文件夾下淘太。
(三):關(guān)于程序被殺掉的斷點續(xù)傳resumeData
根據(jù)上面的分析,基本可以得到以下結(jié)論:
1.DownloadTask每次進(jìn)行斷點續(xù)傳的時候,會根據(jù)data文件中的"路徑Key"去尋找下載文件,然后校驗后再根據(jù)"Range"屬性去進(jìn)行斷點續(xù)傳姻僧。
2.download文件夾中存放的只會是下載中的文件,一旦暫停就會被移動到tmp文件夾下。
3.每個暫停得到的data文件蒲牧,與下載文件一一對應(yīng)撇贺。
3.斷點續(xù)傳只與tmp文件夾中的文件有關(guān)。
具體實現(xiàn)
為了節(jié)省性能冰抢,我嘗試查找關(guān)于程序被殺掉前的回調(diào),但是很遺憾失敗了松嘶,因為我無法控制到知道是哪一秒去保存進(jìn)度,所以我只能每隔一段時間保存一次。設(shè)置一個Bool變量用來判斷是否正在下載中,同時用一個周期事件每隔一段時間暫停一次(聽上去挺笨的挎扰,但是這似乎是唯一獲得data文件的辦法了)翠订。然后保存data文件和拷貝tmp文件夾下的下載文件到安全目錄下(因為tmp文件夾據(jù)說隨時可能清空)。
當(dāng)再次下載的時候遵倦,先是從安全目錄下取到下載文件尽超,刪除tmp文件夾中原有的同名文件,然后copy到tmp目錄下梧躺,最后利用保存的data文件進(jìn)行再次downloadTaskWithResumeData操作似谁,就可以實現(xiàn)再次下載了。
利與弊
好處:
1.DownloadTask可以后臺下載掠哥,不必保持app在前臺巩踏,用戶體驗很好。
2.實現(xiàn)了任意時間點殺掉進(jìn)程后续搀,仍然可以斷點續(xù)傳塞琼。
缺陷:
1.因為蘋果沒有提供很好的API,所以會有一個循環(huán)檢查禁舷,每隔一段時間會暫停個一秒左右,效率略有降低彪杉。
2.如果設(shè)置保存間隔過長,中間殺掉進(jìn)程可能會損失較多進(jìn)度榛了。