溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android基于Flutter如何編寫文件下載管理器

發(fā)布時間:2022-03-25 16:17:21 來源:億速云 閱讀:233 作者:iii 欄目:開發(fā)技術

這篇文章主要介紹“Android基于Flutter如何編寫文件下載管理器”,在日常操作中,相信很多人在Android基于Flutter如何編寫文件下載管理器問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Android基于Flutter如何編寫文件下載管理器”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Dio 的下載方法 download

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:網(wǎng)絡資源的 url

  • savePathdynamic 類型,可以是下載后存儲文件路徑的字符串,也可以是一個返回字符串的回調(diào)方法(Dio 會把 headers 參數(shù)攜帶過去,方便針對下載返回內(nèi)容構建文件路徑);

  • onReceiveProgress:文件接收進度,是一個void Function(int count, int total)回調(diào)函數(shù),調(diào)用者可以通過該回調(diào)方法監(jiān)測下載進度。

  • deleteOnError:發(fā)生錯誤時候是否刪除已下載的文件,默認是 true。

  • lengthHeader:源文件的實際大?。ㄎ磯嚎s前)。默認是 header 的content-length。如果文件壓縮了,而沒有指定該值的話,那進度回調(diào)里的total會是-1;如果使用自定義的 header 指定了文件的大小,那么total會是自定義的 header 對應的文件大小。

  • 其他參數(shù)和普通的請求差不多,這里不再贅述。

為了不暴露下載的具體實現(xiàn),我們在 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());
  }
}

監(jiān)測下載進度

我們新建一個文件下載頁面 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;
// 指示當前是否處于下載中,以便做業(yè)務判斷
bool _downloading = false;

然后我們定義一個下載方法,在下載過程中如果 total 不為-1就更新下載進度,否則提示錯誤(實際調(diào)試發(fā)現(xiàn),如果涉及到需要驗證的,下載后后端實際會返回網(wǎng)頁,這樣也能下載網(wǎng)頁內(nèi)容下來,但是不是想要的文件)。

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('無法獲取文件大小,下載失敗!');
    }
  });
}

這里因為涉及到可能取消,因此只有在沒有取消的情況下才更新下載狀態(tài),要不可能會出現(xiàn)取消的時候還處在下載接收字節(jié)的過程中,雖然取消了但是看到下載進度還在走的情況。

取消下載

取消下載其實很簡單,當我們點擊取消按鈕的時候,調(diào)用 CancelToken 的cancel方法即可。這里我們做了一個判斷,下載比例低于1才可以取消,因為下載完成再取消會拋出異常。同時取消后重置下載比例和顯示的下載百分比。

void _cancelDownload() {
  if (_downloadRatio < 1.0) {
    _token.cancel();
    _downloading = false;
    setState(() {
      _downloadRatio = 0;
      _downloadIndicator = '0.00%';
    });
  }
}

刪除已經(jīng)下載的文件

對于 App,沒有別的入口管理文件,因此實際過程中我們需要提供下載入口供用戶清理已下載的文件。實際已下載的文件,我們需要有下載文件管理功能供用戶管理文件,這個時候會需要本地存儲支撐,我們在后續(xù)的章節(jié)會介紹本地存儲。

刪除文件前需要判斷文件是否存在,如果文件不存在刪除可能拋出異常。文件的管理使用的是 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:應用文檔目錄(不會被系統(tǒng)清除,主要用戶數(shù)據(jù)存儲目錄),對于安卓推薦使用外部存儲getExternalStorageDirectory。

  • getApplicationSupportDirectory:應用支持目錄,一般放置與用戶無關的數(shù)據(jù)。

  • getLibraryDirectory:指向應用可以持久存儲數(shù)據(jù)的目錄,不支持安卓平臺。

  • 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();
}

調(diào)試過程中遇到的一些錯誤

  • OS Error: Read-only file system:安卓系統(tǒng)需要獲取READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE權限。同時需要使用 path_provider獲取應用的文件目錄再往對應的目錄讀寫文件和訪問文件目錄。

  • onReceivedProgress 中如果total=-1則表示該文件被壓縮或者需要會話信息才可以下載(如后端開啟了驗證)。

  • 刪除文件的時候需要檢查文件是否在下載過程中,如果在下載過程中刪除會引起文件讀寫沖突,拋出異常。

  • CancelToken一個實例只能取消一次請求,因此每次發(fā)起請求的時候需要重新構建CancelToken對象,否則取消一次后無法再次取消。

運行結果及代碼

運行結果如下圖所示:

Android基于Flutter如何編寫文件下載管理器

到此,關于“Android基于Flutter如何編寫文件下載管理器”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI