AFNetWorking 實現文件的下載 斷點續傳

最近用到了下載,網上也搜尋過下載方面的東西,沒有找到太合適的關於AFNetWorking 3.x方面的斷點續傳的介紹或者demo,因而本身寫吧。 AFURLSessionManager這個封裝了上傳、下載方面的相關內容,仔細閱讀不難發現,這個就是對 NSURLSession 、NSURLSessionTask 進行的封裝,下載、上傳這些操做用到的就是NSURLSessionTask相關子類。 先說說第一種方式,就是最簡單的下載,用到的方法顯而易見git

/**
  第一種方式
*/
//方法包含了下載所需的 參數 回調 很全面, 這裏返回一個NSURLSessionDownloadTask對象,用於調用系統的方法: resume開始、繼續下載,suspend暫停下載,cancel取消下載
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
                                             progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
                                          destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                                    completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;

/**
  第二種方式 
    能夠實現一種不同的斷點續傳 我我的感受這種方式怪怪的 並且彷佛不能作到關閉app後恢復斷點續傳,雖然能夠保存以前下載的數據,可是下次的請求體就不存在了。
*/
//首先用第一種方法進行開始下載 而後後續暫停操做
//實現斷點的關鍵地方 用這個方法進行取消操做 能夠獲得resumeData
- (void)cancelByProducingResumeData:(void (^)(NSData * _Nullable resumeData))completionHandler;
//而後調用的方法同系統方法

/*系統方法 解釋  Creates a download task with the resume data.  If the download cannot be successfully resumed, URLSession:task:didCompleteWithError: will be called. */
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;

/*AFN方法 繼續進行下載*/
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
                                                progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
                                             destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                                       completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;

//上面這種方法 按照解釋就是不能正常暫停,採用的一種特殊手段暫停下載,而後進行恢復下載,理論上說就是一種日常的下載,爲了處理比較特殊的狀況。至於更好的用法,我暫時尚未發現。

/**
    第三種方式 本文要寫的重點啦 這個方法其實就是代替了系統提供的代理方法進行下載各方面的操做 詳情寫在下面
*/

//獲取文件大小
//文件大小
- (unsigned long long)fileSizeForPath:(NSString *)path {
    unsigned long long fileSize = 0;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:path]) {
        NSError * error = nil;
        NSDictionary * fileDict = [fileManager attributesOfItemAtPath:path error:&error];
        if (!error && fileDict) {
            fileSize =[fileDict fileSize];
        }
    }
    return fileSize;
}
//建立下載請求管理對象
    AFURLSessionManager * manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
//建立流
   NSOutputStream *outputStream = [[NSOutputStream alloc] initWithURL:[NSURL fileURLWithPath:@"文件路徑"] append:YES];
//請求體
    NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:info.url]];
    unsigned long long cacheFileSize = 0;
    cacheFileSize = [self fileSizeForPath:@"文件路徑"];
    if (cacheFileSize) {
        NSString *range = [NSString stringWithFormat:@"bytes=%lld-", cacheFileSize];
        [request setValue:range forHTTPHeaderField:@"Range"];
    }

//下載對象
    NSURLSessionDataTask * task = [manager dataTaskWithRequest:request completionHandler:nil];

//下載接受數據
    [manager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSURLResponse * _Nonnull response) {
        //下載文件的總大小
        response.expectedContentLength + cacheFileSize
        //打開流
        [outputStream open];
        return NSURLSessionResponseAllow;
    }];
    //寫入數據
    [manager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
        
        NSInteger result = [outputStream write:data.bytes maxLength:data.length];
        if (result == -1) {
            //錯誤
            outputStream.streamError;
            [task cancel];
        } else {
            //正確操做
        }
    }];
    //下載完成
    [manager setTaskDidCompleteBlock:^(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSError * _Nullable error) {
        [outputStream close];
        outputStream = nil;
        task = nil;
        if (error) {
        }
    }];

//⚠️  上面的方法其實就是至關於系統的代理方法,具體的能夠去查看 AFURLSessionManager.h 裏面有詳細的說明 demo待我整理整理 github奉上。
相關文章
相關標籤/搜索