<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
檔案下載在很多型別的應用中會涉及,例如音樂、檔案、包括圖片(只是圖片可以使用一些元件完成無感知的下載)。本篇介紹使用 Dio 的下載方法完成檔案的下載,涉及到的內容如下:
download
方法介紹;download
的回撥方法監測下載進度;CancelToken
取消正在下載的任務;path_provider
外掛管理App檔案目錄;Dio 的下載方法定義如下:
Future<Response> download( String urlPath, savePath, { ProgressCallback? onReceiveProgress, Map<String, dynamic>? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, String lengthHeader = Headers.contentLengthHeader, data, Options? options, });
urlPath
:網路資源的 url
;savePath
:dynamic
型別,可以是下載後儲存檔案路徑的字串,也可以是一個返回字串的回撥方法(Dio 會把 headers
引數攜帶過去,方便針對下載返回內容構建檔案路徑);onReceiveProgress
:檔案接收進度,是一個void Function(int count, int total)
回撥函數,呼叫者可以通過該回撥方法監測下載進度。deleteOnError
:發生錯誤時候是否刪除已下載的檔案,預設是 true。lengthHeader
:原始檔的實際大小(未壓縮前)。預設是 header
的content-length
。如果檔案壓縮了,而沒有指定該值的話,那進度回撥裡的total
會是-1
;如果使用自定義的 header
指定了檔案的大小,那麼total
會是自定義的 header
對應的檔案大小。為了不暴露下載的具體實現,我們在 http_util.dart
中封裝一個自己的下載方法。
static Future download( String url, String savePath, { Map<String, dynamic> queryParams, CancelToken cancelToken, dynamic data, Options options, void Function(int, int) onReceiveProgress, }) async { try { return await _dioInstance.download( url, savePath, queryParameters: queryParams, cancelToken: cancelToken, onReceiveProgress: onReceiveProgress, ); } on DioError catch (e) { if (CancelToken.isCancel(e)) { EasyLoading.showInfo('下載已取消!'); } else { if (e.response != null) { _handleErrorResponse(e.response); } else { EasyLoading.showError(e.message); } } } on Exception catch (e) { EasyLoading.showError(e.toString()); } }
我們新建一個檔案下載頁面 file_download.dart
完成檔案下載的範例。這裡定義了幾個屬性來對檔案下載過程進行反饋:
// 檔案下載地址,這裡是谷歌瀏覽器的下載地址(Mac 版本) String _downloadPath = 'https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'; // 下載進度比例,用於檢測下載是否完成 double _downloadRatio = 0.0; // 下載進度百分比 String _downloadIndicator = '0.00%'; // 下載檔案的儲存路徑 String _destPath; // 取消下載的 token CancelToken _token; // 指示當前是否處於下載中,以便做業務判斷 bool _downloading = false;
然後我們定義一個下載方法,在下載過程中如果 total
不為-1
就更新下載進度,否則提示錯誤(實際偵錯發現,如果涉及到需要驗證的,下載後後端實際會返回網頁,這樣也能下載網頁內容下來,但是不是想要的檔案)。
void _downloadFile() { _token = CancelToken(); _downloading = true; HttpUtil.download(_downloadPath, _destPath, cancelToken: _token, onReceiveProgress: (int received, int total) { if (total != -1) { if (!_token.isCancelled) { setState(() { _downloadRatio = (received / total); if (_downloadRatio == 1) { _downloading = false; } _downloadIndicator = (_downloadRatio * 100).toStringAsFixed(2) + '%'; }); } } else { _downloading = false; EasyLoading.showError('無法獲取檔案大小,下載失敗!'); } }); }
這裡因為涉及到可能取消,因此只有在沒有取消的情況下才更新下載狀態,要不可能會出現取消的時候還處在下載接收位元組的過程中,雖然取消了但是看到下載進度還在走的情況。
取消下載其實很簡單,當我們點選取消按鈕的時候,呼叫 CancelToken
的cancel
方法即可。這裡我們做了一個判斷,下載比例低於1才可以取消,因為下載完成再取消會丟擲異常。同時取消後重置下載比例和顯示的下載百分比。
void _cancelDownload() { if (_downloadRatio < 1.0) { _token.cancel(); _downloading = false; setState(() { _downloadRatio = 0; _downloadIndicator = '0.00%'; }); } }
對於 App,沒有別的入口管理檔案,因此實際過程中我們需要提供下載入口供使用者清理已下載的檔案。實際已下載的檔案,我們需要有下載檔案管理功能供使用者管理檔案,這個時候會需要本地儲存支撐,我們在後續的章節會介紹本地儲存。
刪除檔案前需要判斷檔案是否存在,如果檔案不存在刪除可能丟擲異常。檔案的管理使用的是 dart:io 中的方法。
void _deleteFile() { try { File downloadedFile = File(_destPath); if (downloadedFile.existsSync()) { downloadedFile.delete(); } else { EasyLoading.showError('檔案不存在'); } } catch (e) { EasyLoading.showError(e.toString()); } }
path_provider檔案目錄管理
在 App 中沒法直接知道應用的檔案儲存目錄,因此需要借用 path_provider 外掛來獲取 App 的檔案儲存目錄,path_provider
提供瞭如下方法:
getTemporaryDirectory
:應用臨時目錄(可能被清除)getApplicationDocumentsDirectory
:應用檔案目錄(不會被系統清除,主要使用者資料儲存目錄),對於安卓推薦使用外部儲存getExternalStorageDirectory。getApplicationSupportDirectory
:應用支援目錄,一般放置與使用者無關的資料。getLibraryDirectory
:指向應用可以持久儲存資料的目錄,不支援安卓平臺。getExternalStorageDirectory
:獲取外部儲存目錄,不支援 iOS 平臺。getExternalCacheDirectories
:獲取外部快取目錄,,不支援 iOS 平臺。getExternalStorageDirectories
:獲取外部可以的目錄列表,不支援 iOS 平臺。getDownloadsDirectory
:獲取下載目錄,用於 Web 端,不支援安卓和 iOS平臺。通過 path_provider
拿到Directory
物件後,就可以通過 Directory
的 path
屬性獲取到完整的目錄路徑。本例我們是在 initialState 裡獲取檔案儲存路徑的,使用的是臨時目錄。
void initState() { getTemporaryDirectory() .then((tempDir) => {_destPath = tempDir.path + 'googlechrome.dmg'}); super.initState(); }
OS Error: Read-only file system
:安卓系統需要獲取READ_EXTERNAL_STORAGE
和WRITE_EXTERNAL_STORAGE
許可權。同時需要使用 path_provider
獲取應用的檔案目錄再往對應的目錄讀寫檔案和存取檔案目錄。onReceivedProgress
中如果total=-1
則表示該檔案被壓縮或者需要對談資訊才可以下載(如後端開啟了驗證)。CancelToken
一個範例只能取消一次請求,因此每次發起請求的時候需要重新構建CancelToken
物件,否則取消一次後無法再次取消。執行結果如下圖所示:
螢幕錄製2021-07-24 下午9.59.04.gif
從範例可以看到,Dio 的下載方法是簡單易用的,而且提供了友好的下載反饋。同時,藉助 CancelToken 也能取消或者暫停下載(暫停時設定deleteOnError=false,表示不刪除檔案,然後恢復到時候從已下載的偏移量開始,也可以按這種方式做斷點續傳,具體方式可以搜尋或者自己完成)。Dio 網路請求系列的詳細介紹到這一篇結束,後續實際業務用到的時候再穿插介紹,接下來一篇將對 Dio 系列文章做一個整體總結。
以上就是Android基於Flutter編寫檔案下載管理器的詳細內容,更多關於Android檔案下載的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45