本文轉自:http://www.jianshu.com/p/de263da8cdb0
斷點續傳概述:
斷點續傳就是從文件上次中斷的地方開始重新下載或上傳數據,當下載大文件的時候,如果沒有實現斷點續傳功能,那麼每次出現異常或者用戶主動的暫停,都會去重頭下載,這樣很浪費時間。所以斷點續傳的功能就應運而生了
在說IOS斷點續傳之前,下面來簡單介紹 HTTP 斷點續傳的原理
其實斷點續傳的原理很簡單,就是在Http的請求上和一般的下載有所不同而已,舉個例子吧!
1.瀏覽器請求服務器上的一個文件名爲test.zip時,請求內容只展示了一些與本文有關的信息
GET /test.zip HTTP/1.1
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
2.服務器收到請求後,按要求尋找請求的文件,提取文件的信息,然後返回給瀏覽器,返回信息如下:
200
Content-Length=66667777
Accept-Ranges=bytes
Content-Type=application/octet-stream
爲了實現從文件已經下載的地方開始繼續下載。所以在客戶端傳給服務器的時候要多加一條信息--從哪裏開始。下面是客戶端請求時的請求信息,要求從44445555字節開始。
1
GET /test.zip HTTP/1.0
User-Agent: NetFox
RANGE: bytes=44445555-
上面的請求信息多了一個新的字段RANGE RANGE:bytes=44445555-
這段話的意思就是告訴服務器test.zip這個文件從44445555字節開始傳,前面的字節不用傳了。服務器收到這個請求以後,返回的信息如下:
206
Content-Length=66667777
Content-Range=bytes 44445555-66667777
Content-Type=application/octet-stream
和第一次服務器返回的信息相比,增加了一行:
Content-Range=bytes 44445555-66667777
返回的代碼也改爲206了,而不再是200了。
知道了以上原理,就可以進行斷點續傳的編程了。
IOS斷點續傳原理
要實現斷點續傳 , 服務器必須支持(這個很重要,一個巴掌是拍不響的,如果服務器不支持,那麼客戶端寫的再好也沒用)。
// 1 指定下載文件地址 URLString
// 2 獲取保存的文件路徑 filePath
// 3 創建 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];
// 驗證是否下載過文件
if (downloadedBytes > 0) {
// 若下載過 , 斷點續傳的時候修改 HTTP 頭部部分的 Range
NSMutableURLRequest *mutableURLRequest = [request mutableCopy];
NSString *requestRange =
[NSString stringWithFormat:@"bytes=%llu-", downloadedBytes];
[mutableURLRequest setValue:requestRange forHTTPHeaderField:@"Range"];
request = mutableURLRequest;
}
}
// 4 創建 AFHTTPRequestOperation
AFHTTPRequestOperation *operation
= [[AFHTTPRequestOperation alloc] initWithRequest:request];
// 5 設置操作輸出流 , 保存在第 2 步的文件中
operation.outputStream = [NSOutputStream
outputStreamToFileAtPath:filePath append:YES];
// 6 設置下載進度處理 block
[operation setDownloadProgressBlock:^(NSUInteger bytesRead,
long long totalBytesRead, long long totalBytesExpectedToRead) {
// bytesRead 當前讀取的字節數
// totalBytesRead 讀取的總字節數 , 包含斷點續傳之前的
// totalBytesExpectedToRead 文件總大小
}];
// 7 設置 success 和 failure 處理 block
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation
*operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
// 8 啓動 operation
[operation start];
使用以上代碼 , 斷點續傳功能就實現了
總結:
斷點續傳主要依賴於 HTTP 頭部定義的 Range 來完成。有了 Range,應用可以通過 HTTP 請求獲取失敗的資源,從而來恢復下載該資源。當然並不是所有的服務器都支持 Range,但大多數服務器是可以的。Range 是以字節計算的,請求的時候不必給出結尾字節數,因爲請求方並不一定知道資源的大小。
今天只是簡單的介紹了一下,關於斷點續傳其實不止這點知識!下次有時間的話繼續寫,希望各位多多提些意見!多謝!