1. 程式人生 > >檔案下載的三種方式,看這裡就已經足夠了。

檔案下載的三種方式,看這裡就已經足夠了。

檔案下載一(不支援斷點續傳)


這種下載方式用的場合比較少,邏輯比較複雜,程式碼量也比較大。

主要的處理在兩個代理方法中

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    if (self.currentLength) return;
    //檔案路徑
    NSString * caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString * filepath = [caches stringByAppendingPathComponent:@"file.zip"];
    NSLog(@"%@",filepath);
    _path = filepath;
    //建立一個空的檔案到沙河中
    NSFileManager * mgr = [NSFileManager defaultManager];
    [mgr createFileAtPath:filepath contents:nil attributes:nil];
    
    //建立一個用來寫資料的檔案控制代碼
    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
    
    //獲取檔案的大小
    self.totalLength = response.expectedContentLength;
    NSLog(@"--%lld",self.totalLength);
    //    68186536
}

/**
 *  2.當接收到伺服器返回的實體資料時呼叫(具體內容,這個方法可能會被呼叫多次)
 *
 *  @param data       這次返回的資料
 */
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    //移動到檔案的最後面
    [self.writeHandle seekToEndOfFile];
    //將資料寫入到沙河
    [self.writeHandle writeData:data];
    //     NSLog(@"%@",data);
    //累計檔案的長度
    self.currentLength += data.length;
    self.speed = [CountBytes CountBytesBy:data.length];
    self.CircleView.progress = (double)self.currentLength/ self.totalLength;
}

檔案下載二(支援斷點續傳)


所謂斷點續傳就是在某個時刻暫停後,再次下載的時候從之前的進度開始,這就需要我們記錄下暫停之前下載資料。

ok,我們只看暫停和再次開始的程式碼
暫停的程式碼

- (IBAction)pauseClicked:(id)sender {
    
    [self.task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
        _resumeData = resumeData;
        _task = nil;
    }];
    
}

再次恢復下載的程式碼

- (IBAction)continueClicked:(id)sender{
    self.task = [self.session downloadTaskWithResumeData:self.resumeData];
    [self.task resume];
    self.resumeData = nil;
}

檔案下載三(支援斷點續傳)


這種下載方式是站在巨人的肩膀上,這個巨人就是偉大的AFN,在這裡我將其封裝成了下載工具類,只需要傳下載路徑就ok,然後根據block返回的資料進行重新整理執行緒。

核心程式碼

+ (NSURLSessionDownloadTask *)downloadFileWithUrl:(NSString *)url DownloadProgress:(DownloadProgress)progress DownloadCompletion:(CompletionState)completion{
    // 1、 設定請求
    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    // 2、初始化
    NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager * manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    // 3、開始下載
    NSURLSessionDownloadTask * task = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        progress(1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount,1.0 * downloadProgress.totalUnitCount,1.0 * downloadProgress.completedUnitCount);
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        //這裡要返回一個NSURL,其實就是檔案的位置路徑
        NSString * path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        //使用建議的路徑
        path = [path stringByAppendingPathComponent:response.suggestedFilename];
        NSLog(@"%@",path);
        return [NSURL fileURLWithPath:path];//轉化為檔案路徑
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        //如果下載的是壓縮包的話,可以在這裡進行解壓
          NSLog(@"----%@---%d---%@",error.domain,error.code,error);
        //下載成功
        if (error == nil) {
            completion(YES,@"下載完成",[filePath path]);
        }else{//下載失敗的時候,只列舉判斷了兩種錯誤狀態碼
            NSString * message = nil;
            if (error.code == - 1005) {
                message = @"網路異常";
            }else if (error.code == -1001){
                message = @"請求超時";
            }else{
                message = @"未知錯誤";
            }
            completion(NO,message,nil);
        }
    }];
    return task;
}

程式碼傳送門:https://github.com/fuzongjian/DownloadStudy.git順手給個star以資鼓勵,贈人玫瑰。