IOS 下載檔案斷點續傳原理與實現(附原始碼)
阿新 • • 發佈:2019-01-29
在網路狀況不好的情況下,對於檔案的傳輸,我們希望能夠支援可以每次傳部分資料。首先從檔案傳輸協議FTP和TFTP開始分析,
FTP是基於TCP的,一般情況下建立兩個連線,一個負責指令,一個負責資料;而TFTP是基於UDP的,由於UDP傳輸是不可靠的,雖然傳輸速度很快,但對於普通的檔案像PDF這種,少了一個位元組都不行。本次以IM中的檔案下載場景為例,解析基於TCP的檔案斷點續傳的原理,並用程式碼實現。
什麼是斷點續傳?
斷點續傳其實正如字面意思,就是在下載的斷開點繼續開始傳輸,不用再從頭開始。所以理解斷點續傳的核心後,發現其實和很簡單,關鍵就在於對傳輸中斷點的把握,我就自己的理解畫了一個簡單的示意圖:
原理:
斷點續傳的關鍵是斷點,所以在制定傳輸協議的時候要設計好,如上圖,我自定義了一個互動協議,每次下載請求都會帶上下載的起始點,這樣就可以支援從斷點下載了,其實HTTP裡的斷點續傳也是這個原理,在HTTP的頭裡有個可選的欄位RANGE,表示下載的範圍
下面以IOS 開發為例
NSUrlConnection實現斷點續傳的關鍵是自定義http request的頭部的range域屬性。
Range頭域
Range頭域可以請求實體的一個或者多個子範圍。例如,
表示頭500個位元組:bytes=0-499
表示第二個500位元組:bytes=500-999
表示最後500個位元組:bytes=-500
表示500位元組以後的範圍:bytes=500-
第一個和最後一個位元組:bytes=0-0,-1
同時指定幾個範圍:bytes=500-600,601-999
但是伺服器可以忽略此請求頭,如果無條件GET包含Range請求頭,響應會以狀態碼206(PartialContent)返回而不是以200(OK)。
在ios中使用NSMutableURLRequest來定義頭部域
[cpp] view plain copy print?
- NSURL *url1=[NSURL URLWithString:@"下載地址";
-
NSMutableURLRequest* request1=[NSMutableURLRequest requestWithURL:url1];
- [request1 setValue:@"bytes=20000-" forHTTPHeaderField:@"Range"];
- [request1 setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
- NSData *returnData1 = [NSURLConnection sendSynchronousRequest:request1 returningResponse:nil error:nil];
- [self writeToFile:returnData1 fileName:@"SOMEPATH"];
- -(void)writeToFile:(NSData *)data fileName:(NSString *) fileName
- {
- NSString *filePath=[NSString stringWithFormat:@"%@",fileName];
- if([[NSFileManager defaultManager] fileExistsAtPath:filePath] == NO){
- NSLog(@"file not exist,create it...");
- [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
- }else {
- NSLog(@"file exist!!!");
- }
- FILE *file = fopen([fileName UTF8String], [@"ab+" UTF8String]);
- if(file != NULL){
- fseek(file, 0, SEEK_END);
- }
- int readSize = [data length];
- fwrite((constvoid *)[data bytes], readSize, 1, file);
- fclose(file);
- }