1. 程式人生 > >系統網路框架NSURLSession(二)

系統網路框架NSURLSession(二)

  • 產生的原因:在下載檔案的過程中,系統會先把檔案儲存在記憶體中,等到檔案下載完畢之後再寫入到磁碟
  • 解決方案:在下載檔案時,一邊下載一邊寫入到磁碟,減小記憶體使用
  • 在 iOS 中常用的有兩種方法可以實現:
    • NSFileHandle 檔案控制代碼
    • NSOutputStream 輸出流
  • 方案一:NSFileHandle 檔案控制代碼,大致分為四個步驟

    • 對代理方法進行改良

      -(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask 
      didReceiveResponse:(nonnull NSURLResponse
      *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler { //接受到響應的時候 告訴系統如何處理伺服器返回的資料 completionHandler(NSURLSessionResponseAllow); //得到請求檔案的資料大小 self.totalLength = response.expectedContentLength; //拼接檔案的全路徑 NSString *fileName = response.suggestedFilename
      ; NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *fullPath = [cachePath stringByAppendingPathComponent:fileName]; //【1】在沙盒中建立一個空的檔案 [[NSFileManager defaultManager] createFileAtPath:fullPath contents:nil
      attributes:nil]; //【2】建立一個檔案控制代碼指標指向該檔案(預設指向檔案開頭) self.handle = [NSFileHandle fileHandleForWritingAtPath:fullPath]; } -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { //【3】使用檔案控制代碼指標來寫資料(邊寫邊移動) [self.handle writeData:data]; //累加已經下載的檔案資料大小 self.currentLength += data.length; //計算檔案的下載進度 = 已經下載的 / 檔案的總大小 self.progressView.progress = 1.0 * self.currentLength / self.totalLength; } -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { //【4】關閉檔案控制代碼 [self.handle closeFile]; }
  • 方案二:NSOutputStream 輸出流,大致分為三個步驟

    • 對代理方法的處理

      -(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask 
      didReceiveResponse:(nonnull NSURLResponse *)response 
      completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler {
            //接受到響應的時候 告訴系統如何處理伺服器返回的資料
            completionHandler(NSURLSessionResponseAllow);
            //得到請求檔案的資料大小
            self.totalLength = response.expectedContentLength;
            //拼接檔案的全路徑
            NSString *fileName = response.suggestedFilename;
            NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
            NSString *fullPath = [cachePath stringByAppendingPathComponent:fileName];
      
            //(1)建立輸出流,並開啟
            self.outStream = [[NSOutputStream alloc] initToFileAtPath:fullPath append:YES];
            [self.outStream open];
      }
      -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
            //(2)使用輸出流寫資料
            [self.outStream write:data.bytes maxLength:data.length];
            //累加已經下載的檔案資料大小
            self.currentLength += data.length;
            //計算檔案的下載進度 = 已經下載的 / 檔案的總大小
            self.progressView.progress = 1.0 * self.currentLength / self.totalLength;
      }
      -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
            //(3)關閉輸出流
            [self.outStream close];
      }