iOS-檔案斷點續傳,ios-斷點續傳
* 移動用戶端在和伺服器互動的時候,上傳和下載使用十分廣泛。
* 在我們下載檔案的時候,我們在點擊暫停時候可以暫停下載,點擊下載的時候可以繼續下載,這個功能如何??
* 下載進度條如何顯示?
先大概敘述一下斷點下載的原理:
* 首先先判斷要判斷要下載的檔案在本地沙箱中是否存在。
* 如果存在的話,要判斷下載檔案的長度。
* 假設檔案長度是500,我們發起下載請求的時候應該從500開始。
* 點擊暫停下載,應該將連結斷掉。
* 再次點擊下載的時候,根據下載檔案長度,繼續下載。
下面與代碼結合起來敘述具體的實現:
* 假設我們要下載的檔案在伺服器的路徑為:http://localhost:8080:down/xcode_6.dmg;
* 我們將要下載的檔案方法本地沙箱中。檔案命名為:xcode.dmg.
* 擷取檔案儲存路徑的代碼:(摺疊)
1 -(NSString *)getFilePath2 {3 NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];4 NSString *filePath = [documentsPath stringByAppendingPathComponent:@"xcode.dmg"];5 return filePath;6 }下載檔案儲存路徑
* 因為下載的檔案比較大,我們需要採取非同步請求網路。
* 非同步請求網路常用的有四個代理方法。
* 發起網路請求下載。(下載起始點為上次暫停點,判斷上次暫停位置方法是,擷取檔案屬性,從屬性中可以查看檔案長度,請求點為該長度後面的內容)
* 假設向擷取某個位元組的內容,可以使用:
//bytes = 0-499 請求前500個位元組的內容
//bytes = 500- 請求500位元組之後的內容
//bytes = 500-1000 請求資源中某一範圍的內容
//bytes = 0-1,499-500 請求多個範圍之間的內容
* 進度條過去檔案下載進度,可以使用已經下載的檔案的位元組數/檔案的總位元組數。
下面為具體的程式碼片段,裡面有詳細的注釋:
#import <UIKit/UIKit.h>@interface ViewController : UIViewController<NSURLConnectionDataDelegate>{ //進度條變數,顯示檔案下載進度 IBOutlet UIProgressView *_progress; //檔案處理,將下載的檔案寫入本地沙箱 NSFileHandle *_fileHandle; //url串連,點解暫停,取消串連,點擊下載,開始下載 NSURLConnection *_connection; //已經接收資料大小 long long _receiveSize; //檔案總共的大小 long long _totalSize;}//下載按鈕點擊響應函數- (IBAction)download:(id)sender;//暫停按鈕點擊響應函數- (IBAction)pause:(id)sender;@end
- (IBAction)download:(id)sender{ //檔案的路徑 NSString *string = @"http://localhost:8080/down/xcode_6.dmg"; //檔案的路徑轉化為url NSURL *url = [NSURL URLWithString:string]; //建立可變請求 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //判斷沙箱路徑下有沒有這個檔案,YES表示這個檔案已經下載,NO表示還沒有下載 if ([[NSFileManager defaultManager] fileExistsAtPath:[self getFilePath]] == YES) { //根據檔案的屬性,擷取之前下載資料量是多少 NSDictionary *fileDic = [[NSFileManager defaultManager]attributesOfItemAtPath:[self getFilePath] error:nil]; //檔案的長度就是已經下載的資料量 _receiveSize = [fileDic[NSFileSize] longLongValue]; //設定Range,從Range之後的內容開始下載 //bytes = 0-499 請求前500個位元組的內容 //bytes = 500- 請求500位元組之後的內容 //bytes = 500-1000 請求資源中某一範圍的內容 //bytes = 0-1,499-500 請求多個範圍之間的內容 NSString *bytes = [NSString stringWithFormat:@"bytes=%lld-",_receiveSize]; [request setValue:bytes forHTTPHeaderField:@"Range"]; } //發起非同步請求,檔案比較法,使用非同步請求 _connection = [NSURLConnection connectionWithRequest:request delegate:self];}- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ //分析回應標頭 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; //擷取回應標頭,是一個字典 NSDictionary *responseHeader = httpResponse.allHeaderFields; //接收檔案總的大小等於已經下載的資料量,加上為下載的資料量 _totalSize = _receiveSize + [responseHeader[@"Content-Length"] longLongValue]; //建立檔案管理類 NSFileManager *fileManager = [NSFileManager defaultManager]; //沙箱中不存在要下載的檔案,就建立該檔案 if ([fileManager fileExistsAtPath:[self getFilePath]] == NO) { [fileManager createFileAtPath:[self getFilePath] contents:nil attributes:nil]; } //根據路徑寫入檔案 _fileHandle = [NSFileHandle fileHandleForWritingAtPath:[self getFilePath]];}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ //檔案比較大的話,需要多次寫入,寫入的話,需要將游標定位到結尾 [_fileHandle seekToEndOfFile]; //將資料寫入到檔案 [_fileHandle writeData:data]; //最新接收到資料的大小等於檔案中已有的資料,加上剛剛下載的資料量 _receiveSize = _receiveSize + data.length; //計算進度 float jundu = (float)_receiveSize / _totalSize; //使用進度條來表示進度 _progress.progress = jundu;}- (void)connectionDidFinishLoading:(NSURLConnection *)connection{ //檔案完成傳輸,關閉檔案管理 [_fileHandle closeFile];}- (IBAction)pause:(id)sender{ //點擊暫停,取消請求串連 [_connection cancel]; _connection = nil;}-(NSString *)getFilePath{ NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; NSString *filePath = [documentsPath stringByAppendingPathComponent:@"xcode.dmg"]; return filePath;}