iOS網路-04-大檔案下載

來源:互聯網
上載者:User

標籤:ios   網路   

大檔案下載注意事項
  • 若不對下載的檔案進行轉存,會造成記憶體消耗急劇升高,甚至耗盡記憶體資源,造成程式終止。
  • 在檔案下載過程中通常會出現中途停止的狀況,若不做處理,就要重新開始下載,浪費流量。
大檔案下載的解決方案
  • 對下載檔案進行處理,每下載一點資料,就將資料寫到磁碟中(通常是沙箱中),避免在記憶體累積資料(NSURLConnection下載)
    • 使用NSFileHandle類實現寫資料
    • 使用NSOutputStream類實現寫資料
  • 當下載任務終止時,記錄任務終止時的位置資訊,以便下次開始繼續下載
大檔案下載(NSURLConnection)
  • 未支援斷點下載
  • 使用NSURLConnection的代理方式下載檔案
  • 在下載任務的不同階段回調的代理方法中,完成轉移下載檔案,及記錄終止位置的任務
  • 使用NSFileHandle類實現寫資料的下載步驟(完整核心代碼)

    • 設定相關成員屬性
    /**所要下載檔案的總長度*/@property (nonatomic, assign) NSInteger contentLength;/**已下載檔案的總長度*/@property (nonatomic, assign) NSInteger currentLength/**檔案控制代碼,用來實現檔案儲存體*/@property (nonatomic, strong) NSFileHandle *handle;
    • 建立、發送請求
    // 1. 建立請求路徑NSURL *url = [NSURL URLWithString:@"此處為URL字串"];// 2. 將URL封裝成請求NSURLRequest *request = [NSURLRequest requestWithURL:url];// 3. 通過NSURLConnection,並設定代理[NSURLConnection connectionWithRequest:request delegate:self];
    • 遵守代理協議NSURLConnectionDataDelegate,實現代理方法
    /*** 接收到伺服器響應時調用的方法*/- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response{    //擷取所要下載檔案的總長度    self.contentLength = [response.allHeaderFields[@"Content-Length"] integerValue];    //拼接一個沙箱中的檔案路徑    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"minion_15.mp4"];    //建立指定路徑的檔案    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];    //建立檔案控制代碼    self.handle = [NSFileHandle fileHandleForWritingAtPath:filePath];}/*** 接收到伺服器的資料時調用的方法*/- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{    //定位到檔案尾部,將伺服器每次返回的檔案資料都拼接到檔案尾部    [self.handle seekToEndOfFile];    //通過檔案控制代碼,將檔案寫入到沙箱中    [self.handle writeData:data];    //拼接已下載檔案總長度    self.currentLength += data.length;    //計算下載進度    CGFloat progress = 1.0 * self.currentLength / self.contentLength;}/*** 檔案下載完畢時調用的方法*/- (void)connectionDidFinishLoading:(NSURLConnection *)connection{    //關閉檔案控制代碼,並清除    [self.handle closeFile];    self.handle = nil;    //清空已下載檔案長度    self.currentLength = 0;}
  • 使用NSOutputStream類實現寫資料的下載步驟(部分代碼,其他部分代碼同上

    • 設定NSOutputStream成員屬性
    @property (nonatomic, strong) NSOutputStream *stream;
    • 初始化NSOutputStream對象,開啟輸出資料流
    /**接收到伺服器響應的時候調用*/- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{    //擷取下載資料儲存的路徑    NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];    NSString *filePath = [cache stringByAppendingPathComponent:response.suggestedFilename];    //利用NSOutputStream往filePath檔案中寫資料,若append參數為yes,則會寫到檔案尾部    self.stream = [[NSOutputStream alloc] initToFileAtPath:filePath append:YES];    //開啟資料流    [self.stream open];}
    • 寫檔案資料
    /**接收到資料的時候調用*/- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{    [self.stream write:[data bytes] maxLength:data.length];}
    • 關閉輸出資料流
    /**資料下載完畢的時候調用*/- (void)connectionDidFinishLoading:(NSURLConnection *)connection{    [self.stream close];}
大檔案下載(NSURLSession)
  • 支援斷點下載,自動記錄停止下載時斷點的位置
  • 遵守NSURLSessionDownloadDelegate協議
  • 使用NSURLSession下載大檔案,被下載檔案會被自動寫入沙箱的臨時檔案夾tmp中
  • 下載完畢,通常需要將已下載檔案移動其他位置(tmp檔案夾中的資料被定時刪除),通常是cache檔案夾中
  • 詳細的下載步驟

    • 設定下載任務task的為成員變數
    @property (nonatomic, strong) NSURLSessionDownloadTask *task;
    • 擷取NSURLSession對象
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    • 初始化下載任務任務
    self.task = [session downloadTaskWithURL:(此處為下載檔案路徑URL)];
    • 實現代理方法
    /**每當寫入資料到臨時檔案的時候,就會調用一次該方法,通常在該方法中擷取下載進度*/- (void)URLSession:(NSURLSession *)session downloadTask: (NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{    // 計算下載進度    CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;}/**任務終止時調用的方法,通常用於斷點下載*/- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{    //fileOffset:下載任務中止時的位移量}/**遇到錯誤的時候調用,error參數只能傳遞用戶端的錯誤*/- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ }/**下載完成的時候調用,需要將檔案剪下到可以長期儲存的檔案夾中*/- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{    //組建檔案長期儲存的路徑    NSString *file = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];    //擷取檔案控制代碼    NSFileManager *fileManager = [NSFileManager defaultManager];    //通過檔案控制代碼,將檔案剪下到檔案長期儲存的路徑    [fileManager moveItemAtURL:location toURL:[NSURL fileURLWithPath:file] error:nil];}
    • 操作任務狀態
    /**開始/繼續下載任務*/[self.task resume];/**暫停下載任務*/[self.task suspend];

本部落格的最新狀態將會同步到新浪微博帳號:世俗孤島

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

iOS網路-04-大檔案下載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.