日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NSURLSessionDataTask与NSOperationQueue实现多文件断点下载(任意时刻终止进程,重启应用,自动重启下载)...

發布時間:2023/12/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NSURLSessionDataTask与NSOperationQueue实现多文件断点下载(任意时刻终止进程,重启应用,自动重启下载)... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

效果展示

gif有點大,直接連接:7qnbrb.com1.z0.glb.clouddn.com/download.gi…

知識要點

  • NSOperationQueue線程隊列的管理
  • NSURLSession網絡操作
  • FMDB數據庫操作
  • NSOperationQueue

    • 蘋果提供的一套多線程解決方案,基于GCD更高一層的封裝,完全面向對象。

    • 我們使用NSOperation配合NSOperationQueue來實現多線程,執行異步任務。

      NSOperation 實現多線程的使用步驟分為三步:
      1.創建操作:先將需要執行的操作封裝到一個 NSOperation 對象中。
      2.創建隊列:創建 NSOperationQueue 對象。
      3.將操作加入到隊列中:將 NSOperation 對象添加到 NSOperationQueue 對象中。

    • NSOperation是個抽象類,不能用來封裝操作,NSOperation的兩個子類NSInvocationOperation與NSBlockOperation以及自定義繼承自NSOperation的子類。由于我們需要根據NSURLSessionTask的狀態來控制隊列的執行,所以只能自定義NSOperation,并在子類內部通用KVO的方式來監聽NSURLSessionTask狀態

    NSURLSession

    NSURLSession是iOS7中用于替換NSURLConnection而新增的接口,用于網絡相關的操 作,包括數據請求,上傳,下載,處理認證等工具,能處理http協議中的所用事情。但NSURLSession并不直接工作,而是由NSURLSessionTask完成,NSURLSessionTask 有三個子類:數據請求NSURLSessionDataTask,上傳NSURLSessionUploadTask,下載NSURLSessionDownloadTask,可以使用block,delegate來進行初始化,當然使用NSURLSessionDataTask來進行上傳和下載工作也是可行的。 關系結構

    NSURLSessionDataTask與NSURLSessionDownloadTask方案選擇的考慮

    • NSURLSessionDownloadTask

      • 優點:使用cancelByProducingResumeData取消下載時,能獲取到當前下載文件的情況的resumeData,包含下載了多少,總大小等,以及能配置后臺下載功能。
      • 缺點:NSURLSessionDownloadTask下載下來的二進制文件會先存儲在tmp臨時文件(該文件夾下的內容隨時可能清空)中,在下載結束后,才將文件移動到指定的沙盒文件中。
    • NSURLSessionDataTask

      • 優點:直接將二進制數據寫入可以永久存儲的沙盒文件(NSDocumentDirectory,NSLibraryDirectory)中
      • 缺點:需要自定義NSFileHandle,然后將下載的數據拼接存儲在本地
    • 對比:通過兩者的優缺點對比,NSURLSessionDownloadTask如果需要實現在進程終止后,能自啟下載,就必須不斷的將tmp的二進制文件拷貝到NSDocumentDirectory或NSLibraryDirectory中,以及不斷獲取resumeData值,這樣會造成很大的資源的浪費以及內存的開銷。使用NSURLSessionDataTask避免了二進制文件的拷貝,將基礎的數據在開始下載是就存入到數據庫中,從而做到任意時刻終止進程,重啟應用,都能獲取到資源路徑,資源大小,下載的狀態,保持應用終止前的狀態或自動重啟下載。

    • 基于對比,最終我選擇使用NSURLSessionDataTask來實現斷點下載。

    FMDB

    關于FMDB,不做更多的介紹。

    思路

    • 1.準備下載:將下載任務添加到下載任務隊列中,并將文件名稱,資源路徑,下載狀態(等待下載)存儲到數據庫中
    • 2.開始下載:獲取到文件總大小,名稱,更新表數據:下載狀態為正在下載,并將二進制數據使用NSFileHandle寫入沙盒
    • 3.暫停 > 更新表數據:當前下載了多少,下載狀態改成:暫停
    • 4.取消下載 > 數據庫中刪除該條數據,從任務數組中移除該數據
    • 5.下載完成 > 數據庫中刪除該條數據,從任務數組中移除該數據
    • 6.應用被殺掉,重啟應用
      • 6.1.檢查是否有下載隊列
      • 6.2.對于處于下載狀態的隊列,自動啟動
      • 6.33.處于暫停及其它情況的隊列,依然保持原本的情況

    添加下載任務到隊列中

    這里分兩塊:第一次新增,以及由暫停或失敗狀態重啟

    - (void)addDownloadQueue:(NSString *)fileUrl {MHDownloadModel *downloadModel = [self fetchDownloadModelWithFileUrl:fileUrl];if (downloadModel) {return;}//如果數據庫中存在該文件,則表明僅僅只是由暫停或失敗狀態,重啟下載(暫停 -> 正在下載)downloadModel = [[MHFileDatabase shareInstance] queryModelWitFileName:fileUrl.lastPathComponent];if (downloadModel) {//更新下載文件的狀態[[MHFileDatabase shareInstance] updateDownloadStatusWithFileName:fileUrl.lastPathComponent downloadStatus:MHDownloadStatusDownloading];} else {//插入數據,記錄下載文件[[MHFileDatabase shareInstance] insertFileWithFileName:fileUrl.lastPathComponent filePath:fileUrl fileTotalSize:0];downloadModel = [MHDownloadModel new];downloadModel.filePath = fileUrl;}[self.downloadTasks addObject:downloadModel];[self startDownLoadWithUrl:fileUrl]; } 復制代碼

    啟動下載任務

    此時并不一定馬上下載,下載的啟動由NSOperationQueue控制,默認最大的下載并發數為3。

    - (void)startDownLoadWithUrl:(NSString *)url {MHDownloadModel *downloadModel = [self fetchDownloadModelWithFileUrl:url];downloadModel.downloadStatus = MHDownloadStatusDownloadWait;NSURLSessionDataTask *task = downloadModel.task;if (task && task.state == NSURLSessionTaskStateRunning) {return;}__weak typeof(self) weakSelf = self;MHURLSessionTaskOperation *operation = [MHURLSessionTaskOperation operationWithURLSessionTask:nil sessionBlock:^NSURLSessionTask *{__strong typeof(weakSelf) strongSelf = weakSelf;NSLog(@"thread : %@, MHCustomOperation operationWithURLSessionTask", [NSThread currentThread]);return [strongSelf downloadDataTaskWithUrl:url];}];[self.operationQueue addOperation:operation]; } 復制代碼

    封裝下載請求:

    1.設置url
    2.設置request,設置請求頭、請求體
    3.發送請求

    - (NSURLSessionDataTask *)downloadDataTaskWithUrl:(NSString *)url{NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];NSDictionary *dic = [[NSFileManager defaultManager] attributesOfItemAtPath:[self getFilePathWithUrl:url] error:nil];MHDownloadModel *downloadModel = [self fetchDownloadModelWithFileUrl:url];downloadModel.currentSize = [dic[@"NSFileSize"] integerValue];[request setValue:[NSString stringWithFormat:@"bytes=%zd-",downloadModel.currentSize] forHTTPHeaderField:@"Range"];NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];NSLog(@"thread : %@, 執行下載 --- %s", [NSThread currentThread], __func__);downloadModel.task = dataTask;return dataTask; } 復制代碼

    實現代理NSURLSessionDataDelegate

    • 開始下載:獲取目標 文件的大小,創建沙盒文件 必須調用 completionHandler (NSURLSessionResponseAllow)
    - (void)URLSession:(NSURLSession *)sessiondataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)responsecompletionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler 復制代碼
    • 獲取下載進度,并將二進制數據寫入沙盒
    - (void)URLSession:(NSURLSession *)sessiondataTask:(NSURLSessionDataTask *)dataTaskdidReceiveData:(NSData *)data 復制代碼
    • 下載完成或出錯
    - (void)URLSession:(NSURLSession *)sessiontask:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error 復制代碼

    完整案例:Github

    轉載于:https://juejin.im/post/5b8bb41b51882542c43a0843

    總結

    以上是生活随笔為你收集整理的NSURLSessionDataTask与NSOperationQueue实现多文件断点下载(任意时刻终止进程,重启应用,自动重启下载)...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。