1.如果使用斷點續(xù)傳,不僅僅是客戶端的工作,還需要服務器支持斷點續(xù)傳功能,否則無法生成正確的resumeData,
如何驗證服務器是否支持斷點續(xù)傳呢?
我們可以通過下載文件的時候的響應頭來查看:
根據(jù)蘋果官方文檔描述:
滿足上述條件的 才能使用斷點續(xù)傳功能
其次,使用斷點續(xù)傳的時候,客戶端請求的range是比如說是 19799+ ,服務器此時返回的文件的部分數(shù)據(jù),服務器響應碼必須是 206,不可以是200或者其他狀態(tài)碼,否則客戶端會從頭下載,
---2018-09-5補充-----
先說說斷點續(xù)傳 :
最近重構公司代碼,公司需要做文件的斷點續(xù)傳,看了下之前的代碼和網上的代碼,大家還有好多是使用的NSURLConnection,
一點一點的拼接data,然后斷開連接,再次連接的時候,將本地的data的長度,塞到請求頭里面設置range
[request setValue:rangeString forHTTPHeaderField:@"Range"];
這種的,但是我們的網絡請求是封裝的AFNetworking的,也發(fā)現(xiàn)AFNetworking也有NSURLSessionDownLoadTask,我們就拿過來接著就用了,其實AFNetworking也支持斷點續(xù)傳,而且支持的我感覺還是很完美的.
---2019-01-24補充----
如果是做下載工具或者使用的默認的defaultConfig的話,需要注意一下iOS默認的限制同一個服務器tcp連接的并發(fā)數(shù)量限制,否則會發(fā)現(xiàn) ,無論創(chuàng)建多少下載任務,都是4個或者6個在運行,其他的在排隊,甚至還最后直接超時了
我整理了一下并發(fā)的一些基礎的個人理解:NSURLSession的最大并發(fā) HTTPMaximumConnectionsPerHost屬性使用場景
---2019-01-24補充----
首先,我們創(chuàng)建一個管理下載的manager及下載的配置,注意那個后臺任務的backgroundSessionConfigurationWithIdentifier是要確定的,要后臺下載的時候使用
注意代碼中的一個AF的通知監(jiān)聽,特別重要,后臺下載的回調及下載成功失敗的回調,都是在這個通知里面(其實是AFNetworking封裝了,把回調信息都是通過通知傳遞的,在這里真的佩服AFNetworking作者,把通知用的這么出神入化,我是在這里重新對通知的認知提高了一個大的階段,這里只是上了一點發(fā)送通知的地方,通知的userInfo帶了很多東西,詳細的大家可以看下AF的源碼)
AFURLSessionManager開始一個下載的時候,有兩個方法,分別是開始下載(重頭下載),繼續(xù)下載(需要傳入一個resumeData)
看方法名,作者就給我們做了斷點續(xù)傳的功能
介紹完這兩個方法名,我們介紹下第一個方法是怎么使用,和第二個是什么使用的,并且resumeData是在哪里獲取的
1.當我們需要下載的時候,主動去調用downloadTaskWithRequest方法,根據(jù)下載地址url,去判斷本地是否有resumeData,這個類似SDWebImage的實現(xiàn),我們自己去維護這個對應關系,可以存到本地一個plist文件里面,鍵值對對應 url:resumeData ,
開始下載的時候,去判斷當前是否存在這個url:resumeData,存在的話,看一下長度是否大于零(當用戶開始下載的時候,如果什么都沒下載到,就中斷下載,resumeData是nil,如果直接寫入plist是會崩潰的,我們可以寫一個空字符串,雖然不是一個類型,但是length都可以使用,不會太影響),大于零,就使用resumeData調用downloadTaskWithResumeData這個方法,然后去開始我們的任務
上面是兩個基本的方法介紹,這里介紹一下那個ResumeData在哪里獲取,什么時候獲取,
還是上面提到的那個通知? (是在NSURLSessionTaskDelegate? 這個協(xié)議里面的- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error? 這個方法發(fā)出了的,其實downLoadTask的成功,失敗,中斷都會調用這個方法),所以,我們需要去剛剛那個通知里面去看看到底都傳過來什么.
拿到了這個ResumeData,大家就可以區(qū)分使用什么時候開始斷點續(xù)傳,什么時候重新下載了
大家可以主動去將task 提前結束來觸發(fā)那個通知,一般不允許蜂窩下載的時候,會用到這個方法
后臺下載 :
后臺下載呢,其實上面初始化那個manger的時候,配置那個后臺配置的時候,已經實現(xiàn)了后臺下載的過程,你可以嘗試下,你調回前臺,你的下載也在繼續(xù),只是這個時候,你的session被操作系統(tǒng)接過去了,操作系統(tǒng)去管理了,一旦你下載完成,會通知你(如果你的app還活著的時候),那么你的app死了的時候怎么辦呢,操作系統(tǒng)會給你留著,持有者,等你的app再次復活的時候,并且再次創(chuàng)建NSURLSessionConfiguration,有后臺任務,并且后臺的backgroundSessionConfigurationWithIdentifier一致的話,操作系統(tǒng)會去調用你的原來的NSURLSessionTaskDelegate代理中的task的didCompleteWithError的方法,由于我們的使用的是AF封裝的,所以那個代理被AF接到并且通過通知處理了,所以還是會在我們之前監(jiān)聽的那個通知里面,和我們app活著的時候一樣一樣的,去發(fā)送那個AFNetworkingTaskDidCompleteNotification的通知,在這里 我們原來的處理邏輯不需要改變,
上面講的是我們進入后臺,app慢慢的被系統(tǒng) 殺死 或者沒殺死的時候,那么,如果我正在下載著,app崩潰,或者被用戶手動強退怎么辦? 經過驗證,其實是一樣的,出現(xiàn)這個情況后,操作系統(tǒng)監(jiān)聽到被殺死或者被中斷,也會幫我們持有這個session,然后把崩潰的一瞬間的ResumeData存著,等待我們再次創(chuàng)建相同后綴的session,那時候在調用回調---->af再發(fā)通知---->我們再存起來.
講了這么多,大家是不是特別好奇,這個resumeData到底是什么?
其實resumeData是一個data類型,大家可以轉成字符串,看一下里面的內容
他的本質是一個xml文件
AF在下載的時候(其實是調用的系統(tǒng)的下載方法),會將文件先下載到沙盒目錄下的temp文件夾中,生成一個后綴為tmp的文件,等我們下載完的時候,會將文件處理,然后移動到我們下載時設置的路徑下,這樣,我們的下載任務就完成了,
在上面的xml文件中,大家可以看到下載的url,當前接受的文件大小,第幾次下載,還有臨時文件名等信息,其實本質還是萬變不離其宗,但是感覺這樣用起來挺好的,既然用了AF了,就用到底吧,這樣 ,我們基本的斷點續(xù)傳和后臺下載是說完了,有錯誤希望大家指出,共同進步,謝謝
對了,參考過一個同學關于后臺下載的講解,大家可以看一下
來源:http://www.reibang.com/p/83fd0fcdf898