NSURLSession實現斷點續傳

NSURLSession VS NSURLConnection 
NSURLSession可以看做是NSURLConnection的進化版,其對NSURLConnection的改進點有: 

  • * 根據每個Session做配置(http header,Cache,Cookie,protocal,Credential),不再在整個App層面共享配置.
  • * 支持網絡操作的取消和斷點續傳
  • * 改進了授權機制的處理
  • * 豐富的Delegate模型
  • * 分離了真實數據和網絡配置數據。
  • * 後臺處理上傳和下載,即使你點擊了“Home”按鈕,後臺仍然可以繼續下載,並且提供了根據網絡狀況,電力情況進行處理的配置。

用法 
使用NSURLSession的一般套路如下: 
  • 1. 定義一個NSURLRequest
  • 2. 定義一個NSURLSessionConfiguration,配置各種網絡參數
  • 3. 使用NSURLSession的工廠方法獲取一個所需類型的NSURLSession
  • 4. 使用定義好的NSURLRequest和NSURLSession構建一個NSURLSessionTask
  • 5. 使用Delegate或者CompletionHandler處理任務執行過程的所有事件。

實戰 

這兒我簡單的實現了一個下載任務的斷點續傳功能,具體實現代碼如下:

-(NSURLSession *)session{

    if(_session == nil){

        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

        _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

    }

    return _session;

}


-(NSURLRequest *)request{

    if(_request == nil){

        NSURL *url = [NSURL URLWithString:@"http://p1.pichost.me/i/40/1639665.png"];

        _request = [NSURLRequest requestWithURL:url];

    }

    return _request;

}

-(void)startAction{

    if(self.isLoading){

        NSLog(@"loading...");

        return;

    }

    

    NSLog(@"start download task");

    

    self.task = [self.session downloadTaskWithRequest:self.request];

    [self.task resume];

}


-(void)pauseAction{

    if(_task){

        NSLog(@"pause download task");

        

        //取消下載任務,把已下載數據保存起來

       [self.task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {

           self.imgData = resumeData;

           self.task = nil;

       }];

    }

}


-(void)resumeAction{

    if(!_task){

        NSLog(@"resume download task");

        

        //判斷是否有已下載數據,有則直接斷點續傳,沒有則重新下載

        if(self.imgData){

            self.task = [self.session downloadTaskWithResumeData:self.imgData];

        }else{

            self.task = [self.session downloadTaskWithRequest:self.request];

        }

        [self.task resume];

    }

}


#pragma mark delegate

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{

    //下載成功後,文件是保存在一個臨時目錄的,需要開發者自己考到放置該文件的目錄

    NSLog(@"Download success for URL: %@",location.description);

    NSURL *destination = [self createDirectoryForDownloadItemFromURL:location];

    BOOL success = [self copyTempFileAtURL:location toDestination:destination];

    

    if(success){

        //        文件保存成功後,使用GCD調用主線程把圖片文件顯示在UIImageView

        dispatch_async(dispatch_get_main_queue(), ^{

            UIImage *image = [UIImage imageWithContentsOfFile:[destination path]];

            self.imgView.image = image;

            self.imgView.contentMode = UIViewContentModeScaleAspectFit;

        });

    }else{

        NSLog(@"Meet error when copy file");

    }

    self.task = nil;

}


/* Sent periodically to notify the delegate of download progress. */

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask

      didWriteData:(int64_t)bytesWritten

 totalBytesWritten:(int64_t)totalBytesWritten

totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

{

    //刷新進度條的delegate方法,同樣的,獲取數據,調用主線程刷新UI

    double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite;

    dispatch_async(dispatch_get_main_queue(), ^{

        self.infoLabel.text = [NSString stringWithFormat:@"進度: %.2f%%", currentProgress];

    });

}


//創建文件本地保存目錄

-(NSURL *)createDirectoryForDownloadItemFromURL:(NSURL *)location

{

    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];

    NSURL *documentsDirectory = urls[0];

    return [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]];

}


//把文件拷貝到指定路徑

-(BOOL) copyTempFileAtURL:(NSURL *)location toDestination:(NSURL *)destination

{

    NSError *error;

    NSFileManager *fileManager = [NSFileManager defaultManager];

    [fileManager removeItemAtURL:destination error:NULL];

    [fileManager copyItemAtURL:location toURL:destination error:&error];

    if (error == nil) {

        return true;

    }else{

        NSLog(@"%@",error);

        return false;

    }

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章