斷點(diǎn)續(xù)傳概述:
斷點(diǎn)續(xù)傳就是從文件上次中斷的地方開始重新下載或上傳數(shù)據(jù),當(dāng)下載大文件的時(shí)候,如果沒有實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能,那么每次出現(xiàn)異?;蛘哂脩糁鲃?dòng)的暫停,都會(huì)去重頭下載,這樣很浪費(fèi)時(shí)間。所以斷點(diǎn)續(xù)傳的功能就應(yīng)運(yùn)而生了
在說IOS斷點(diǎn)續(xù)傳之前,下面來簡單介紹 HTTP 斷點(diǎn)續(xù)傳的原理
其實(shí)斷點(diǎn)續(xù)傳的原理很簡單,就是在Http的請求上和一般的下載有所不同而已,舉個(gè)例子吧!
1.瀏覽器請求服務(wù)器上的一個(gè)文件名為test.zip時(shí),請求內(nèi)容只展示了一些與本文有關(guān)的信息
GET /test.zip HTTP/1.1
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
2.服務(wù)器收到請求后,按要求尋找請求的文件,提取文件的信息,然后返回給瀏覽器,返回信息如下:
200
Content-Length=66667777
Accept-Ranges=bytes
Content-Type=application/octet-stream
為了實(shí)現(xiàn)從文件已經(jīng)下載的地方開始繼續(xù)下載。所以在客戶端傳給服務(wù)器的時(shí)候要多加一條信息--從哪里開始。下面是客戶端請求時(shí)的請求信息,要求從44445555字節(jié)開始。
1
GET /test.zip HTTP/1.0
User-Agent: NetFox
RANGE: bytes=44445555-
上面的請求信息多了一個(gè)新的字段RANGE RANGE:bytes=44445555-
這段話的意思就是告訴服務(wù)器test.zip這個(gè)文件從44445555字節(jié)開始傳,前面的字節(jié)不用傳了。服務(wù)器收到這個(gè)請求以后,返回的信息如下:
206
Content-Length=66667777
Content-Range=bytes 44445555-66667777
Content-Type=application/octet-stream
和第一次服務(wù)器返回的信息相比,增加了一行:
Content-Range=bytes 44445555-66667777
返回的代碼也改為206了,而不再是200了。
知道了以上原理,就可以進(jìn)行斷點(diǎn)續(xù)傳的編程了。
IOS斷點(diǎn)續(xù)傳原理
要實(shí)現(xiàn)斷點(diǎn)續(xù)傳 , 服務(wù)器必須支持(這個(gè)很重要,一個(gè)巴掌是拍不響的,如果服務(wù)器不支持,那么客戶端寫的再好也沒用)。
// 1 指定下載文件地址 URLString
// 2 獲取保存的文件路徑 filePath
// 3 創(chuàng)建 NSURLRequest
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URLString]];
unsigned long long downloadedBytes = 0;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
// 3.1 若之前下載過 , 則在 HTTP 請求頭部加入 Range
// 獲取已下載文件的 size
downloadedBytes = [self fileSizeForPath:filePath];
// 驗(yàn)證是否下載過文件
if (downloadedBytes > 0) {
// 若下載過 , 斷點(diǎn)續(xù)傳的時(shí)候修改 HTTP 頭部部分的 Range
NSMutableURLRequest *mutableURLRequest = [request mutableCopy];
NSString *requestRange =
[NSString stringWithFormat:@"bytes=%llu-", downloadedBytes];
[mutableURLRequest setValue:requestRange forHTTPHeaderField:@"Range"];
request = mutableURLRequest;
}
}
// 4 創(chuàng)建 AFHTTPRequestOperation
AFHTTPRequestOperation *operation
= [[AFHTTPRequestOperation alloc] initWithRequest:request];
// 5 設(shè)置操作輸出流 , 保存在第 2 步的文件中
operation.outputStream = [NSOutputStream
outputStreamToFileAtPath:filePath append:YES];
// 6 設(shè)置下載進(jìn)度處理 block
[operation setDownloadProgressBlock:^(NSUInteger bytesRead,
long long totalBytesRead, long long totalBytesExpectedToRead) {
// bytesRead 當(dāng)前讀取的字節(jié)數(shù)
// totalBytesRead 讀取的總字節(jié)數(shù) , 包含斷點(diǎn)續(xù)傳之前的
// totalBytesExpectedToRead 文件總大小
}];
// 7 設(shè)置 success 和 failure 處理 block
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation
*operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
// 8 啟動(dòng) operation
[operation start];
使用以上代碼 , 斷點(diǎn)續(xù)傳功能就實(shí)現(xiàn)了
總結(jié):
斷點(diǎn)續(xù)傳主要依賴于 HTTP 頭部定義的 Range 來完成。有了 Range,應(yīng)用可以通過 HTTP 請求獲取失敗的資源,從而來恢復(fù)下載該資源。當(dāng)然并不是所有的服務(wù)器都支持 Range,但大多數(shù)服務(wù)器是可以的。Range 是以字節(jié)計(jì)算的,請求的時(shí)候不必給出結(jié)尾字節(jié)數(shù),因?yàn)檎埱蠓讲⒉灰欢ㄖ蕾Y源的大小。
今天只是簡單的介紹了一下,關(guān)于斷點(diǎn)續(xù)傳其實(shí)不止這點(diǎn)知識(shí)!下次有時(shí)間的話繼續(xù)寫,希望各位多多提些意見!多謝!