1.斷點(diǎn)續(xù)傳
定義:我們有時(shí)在邊聊天邊下載大文件時(shí),感覺(jué)很卡,這時(shí)可以暫停下載任務(wù),聊完天再繼續(xù)下載文件。這就是斷點(diǎn)下載
實(shí)現(xiàn)方式:iOS中利用NSURLSession可以進(jìn)行文件斷點(diǎn)下載,下面就一起來(lái)實(shí)現(xiàn)它吧。
知識(shí)儲(chǔ)備:1.對(duì)NSURLSesiion的認(rèn)識(shí)
NSURLSesiion是蘋(píng)果在iOS7推出的一個(gè)類,它具備了NSURLConnection所具備的方法,同時(shí)也比它更強(qiáng)大。蘋(píng)果推出它的目的大有取代NSURLConnection的趨勢(shì)或者目的。
2.NSURLSesiion的作用
實(shí)現(xiàn)對(duì)文件的下載與上傳。在NSURLSesiion中,任何請(qǐng)求都可以被看做是一個(gè)任務(wù)。而NSURLSesiionData有兩個(gè)子類:NSURLSessionDownlaodTask實(shí)現(xiàn)文件下載和NSURLSessionUploadTask實(shí)現(xiàn)文件上傳。
3.NSURLSession的獲取
NSURLSession的獲取可以用NSURLSessionDownloadTaskdelegate的方法獲取,但是必須得遵循這個(gè)協(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的代理方法:
它有三個(gè)方法:
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];
第二部分對(duì)程序幾個(gè)屬性的說(shuō)明
1.resumeData
該參數(shù)包含了繼續(xù)下載文件的位置信息。也就是說(shuō),當(dāng)你下載了10M得文件數(shù)據(jù),暫停了。那么你下次繼續(xù)下載的時(shí)候是從第10M這個(gè)位置開(kāi)始的,而不是從文件最開(kāi)始的位置開(kāi)始下載。因而為了保存這些信息,所以才定義了這個(gè)NSData類型的這個(gè)屬性:resumeData
2. ?task
該參數(shù)的類型是NSURLSessionDownloadTask。因?yàn)樵诔绦蛘{(diào)用暫停(pause)這個(gè)方法時(shí),必須擁有這個(gè)屬性,怎么拿到它了?最好的辦法就是讓控制器擁有這個(gè)屬性。
3. session
該參數(shù)的類型是NSURLSession.在程序調(diào)用繼續(xù)下載(resume)這個(gè)方法時(shí),必須擁有這個(gè)session。因?yàn)橹暗娜蝿?wù)task被取消了,無(wú)法在復(fù)用了,所以用懶加載的方法,讓session只創(chuàng)建一次,同時(shí)也讓控制器擁有了這個(gè)屬性。
*使用NSURLSessionDataTask可以很輕松實(shí)現(xiàn)斷點(diǎn)續(xù)傳,可是有個(gè)致命的缺點(diǎn)就是無(wú)法進(jìn)行后臺(tái)下載
二:對(duì)NSURLSessionDownloadTask解釋
? ? ? ? 使用NSURLSessionDataTask可以很輕松實(shí)現(xiàn)斷點(diǎn)續(xù)傳,可是有個(gè)致命的缺點(diǎn)就是無(wú)法進(jìn)行后臺(tái)下載,一點(diǎn)應(yīng)用程序進(jìn)入了后臺(tái),便會(huì)停止下載。所以無(wú)法滿足我們的需求。而NSURLSessionDownloadTask是唯一可以實(shí)現(xiàn)后臺(tái)下載的類,所以我們只能從這個(gè)類進(jìn)行下手了。
那么本篇我們就來(lái)談?wù)勱P(guān)于應(yīng)用程序隨時(shí)可能被殺死的情況下,如何進(jìn)行斷點(diǎn)續(xù)傳。
(一):關(guān)于斷點(diǎn)續(xù)傳原理:
首先,如果想要進(jìn)行斷點(diǎn)續(xù)傳,那么需要簡(jiǎn)單了解一下斷點(diǎn)續(xù)傳的工作機(jī)制,在HTTP請(qǐng)求頭中,有一個(gè)Range的關(guān)鍵字,通過(guò)這個(gè)關(guān)鍵字可以告訴服務(wù)器返回哪些數(shù)據(jù)給我。
比如:
bytes=500-999 表示第500-第999字節(jié)
bytes=500- 表示從第500字節(jié)往后的所有字節(jié)
然后我們?cè)俑鶕?jù)服務(wù)器返回的數(shù)據(jù),將得到的data數(shù)據(jù)拼接到文件后面,就可以實(shí)現(xiàn)斷點(diǎn)續(xù)傳了。
(二):關(guān)于文件下載與暫停的分析:
1.當(dāng)使用NSURLSessionDownloadTask進(jìn)行下載的時(shí)候,系統(tǒng)會(huì)在cache文件夾下創(chuàng)建一個(gè)下載的路徑.(路徑下會(huì)有一個(gè)以"CFNetworking"打頭的.tmp文件(以下簡(jiǎn)稱"下載文件"防止混淆),這個(gè)就是我們正在下載中的文件)
2.調(diào)用cancelByProducingResumeData:方法后,會(huì)得到一個(gè)data文件,通過(guò)String格式化后,發(fā)現(xiàn)是一個(gè)XML文件.
3.XML里面包含了關(guān)于.tmp文件的一些關(guān)鍵點(diǎn)的描述,包括"Range","key","下載文件的路徑"等等.而原本存在于download文件下的下載文件,則被移動(dòng)到了系統(tǒng)tmp文件夾目錄下.
4.當(dāng)我們?cè)俅芜M(jìn)行resume操作的時(shí)候,下載文件則又被移回到了download文件夾下。
(三):關(guān)于程序被殺掉的斷點(diǎn)續(xù)傳resumeData
根據(jù)上面的分析,基本可以得到以下結(jié)論:
1.DownloadTask每次進(jìn)行斷點(diǎn)續(xù)傳的時(shí)候,會(huì)根據(jù)data文件中的"路徑Key"去尋找下載文件,然后校驗(yàn)后再根據(jù)"Range"屬性去進(jìn)行斷點(diǎn)續(xù)傳。
2.download文件夾中存放的只會(huì)是下載中的文件,一旦暫停就會(huì)被移動(dòng)到tmp文件夾下。
3.每個(gè)暫停得到的data文件,與下載文件一一對(duì)應(yīng)。
3.斷點(diǎn)續(xù)傳只與tmp文件夾中的文件有關(guān)。
具體實(shí)現(xiàn)
為了節(jié)省性能,我嘗試查找關(guān)于程序被殺掉前的回調(diào),但是很遺憾失敗了,因?yàn)槲覠o(wú)法控制到知道是哪一秒去保存進(jìn)度,所以我只能每隔一段時(shí)間保存一次。設(shè)置一個(gè)Bool變量用來(lái)判斷是否正在下載中,同時(shí)用一個(gè)周期事件每隔一段時(shí)間暫停一次(聽(tīng)上去挺笨的,但是這似乎是唯一獲得data文件的辦法了)。然后保存data文件和拷貝tmp文件夾下的下載文件到安全目錄下(因?yàn)閠mp文件夾據(jù)說(shuō)隨時(shí)可能清空)。
當(dāng)再次下載的時(shí)候,先是從安全目錄下取到下載文件,刪除tmp文件夾中原有的同名文件,然后copy到tmp目錄下,最后利用保存的data文件進(jìn)行再次downloadTaskWithResumeData操作,就可以實(shí)現(xiàn)再次下載了。
利與弊
好處:
1.DownloadTask可以后臺(tái)下載,不必保持app在前臺(tái),用戶體驗(yàn)很好。
2.實(shí)現(xiàn)了任意時(shí)間點(diǎn)殺掉進(jìn)程后,仍然可以斷點(diǎn)續(xù)傳。
缺陷:
1.因?yàn)樘O(píng)果沒(méi)有提供很好的API,所以會(huì)有一個(gè)循環(huán)檢查,每隔一段時(shí)間會(huì)暫停個(gè)一秒左右,效率略有降低。
2.如果設(shè)置保存間隔過(guò)長(zhǎng),中間殺掉進(jìn)程可能會(huì)損失較多進(jìn)度。