Flutter:文件上传与下载(下载后预览)

Dio

dio是一个强大的Dart Http请求库,提供了丰富的功能和易于使用的API,支持文件上传和下载。

这个就不介绍了,网上有很多的封装案例。

background_downloader

简介

适用于iOS,Android,MacOS,Windows和Linux的后台文件下载器和上传器。

官方文档
https://pub-web.flutter-io.cn/packages/background_downloader

安装

dart 复制代码
flutter pub add background_downloader

示例1:下载

dart 复制代码
class _MyHomePageState extends State<MyHomePage> {
  // 文件信息
  String fileInfo = '';
  // 下载进度
  double progress = 0.0;
  // 任务状态
  String taskStatus = '';
  // 任务
  late DownloadTask task;

  // 下载单个文件
  _downloadFile() async {
    task = DownloadTask(
        url:
            'https://vd3.bdstatic.com/mda-ma6igm4b0znfbqve/sc/cae_h264_nowatermark/1609998111/mda-ma6igm4b0znfbqve.mp4', // 下载地址
        // urlQueryParameters: {'q': 'pizza'},  // 请求参数
        filename: 'mov_bbb.mp4', // 文件名
        //headers: {'myHeader': 'value'},  请求头
        directory: 'my_sub_directory', // 文件存储目录
        updates: Updates.statusAndProgress, // 更新任务状态和下载进度
        requiresWiFi: true, // 使用wifi
        retries: 5, // 下载的重试次数
        allowPause: true, // 运行暂停
        metaData: 'data for me' // 元数据,可以存储一些对于下载任务有用的信息,方便后续相关操作
        );
    // 监听下载
    final result =
        await FileDownloader().download(task, onProgress: (progress) {
      setState(() {
        this.progress = progress;
      });
    }, onStatus: (states) {
      String msg = '';
      if (states == TaskStatus.complete) {
        msg = '下载完成';
        //  下载完成后,将文件移动到共享目录后,其他应用也可以访问。否则只能在本应用内访问
        FileDownloader().moveToSharedStorage(task, SharedStorage.downloads);
      } else if (states == TaskStatus.canceled) {
        msg = '已取消';
        setState(() {
          progress = 0;
        });
      } else if (states == TaskStatus.paused) {
        msg = '已暂停';
      } else if (states == TaskStatus.running) {
        msg = '下载中...';
      } else {
        msg = '下载失败';
      }
      setState(() {
        taskStatus = msg;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text(widget.title),
        ),
        body: Column(
          children: [
            const SizedBox(
              height: 20,
            ),
            Text("文件信息:$fileInfo"),
            const SizedBox(
              height: 20,
            ),
            Row(
              children: [
                const Text("下载进度:"),
                Expanded(
                    child: LinearProgressIndicator(
                  value: progress,
                  backgroundColor: Colors.greenAccent,
                  valueColor: const AlwaysStoppedAnimation<Color>(Colors.red),
                )),
                Text("${(progress * 100).toStringAsFixed(1)}%")
              ],
            ),
            Text("任务状态:$taskStatus"),
            const SizedBox(
              height: 20,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              mainAxisSize: MainAxisSize.max,
              children: [
                ElevatedButton(
                    onPressed: _downloadFile, child: const Text("下载")),
                ElevatedButton(
                    onPressed: () async {
                      // 暂停任务
                      await FileDownloader().pause(task);
                    },
                    child: const Text("暂停")),
                ElevatedButton(
                    onPressed: () async {
                      //  根据固定的任务id取消
                      await FileDownloader().cancelTaskWithId(task.taskId);
                      // 取消所有
                      //FileDownloader().cancelTasksWithIds(taskIds)
                    },
                    child: const Text("取消")),
                ElevatedButton(
                    onPressed: () async {
                      await FileDownloader().resume(task);
                    },
                    child: const Text("恢复"))
              ],
            )
          ],
        ));
  }
}

注意:

  • 默认下载的文件是在本应用内,其他应用无访问权限。要想要被访问到需要在下载完成后执行 FileDownloader().moveToSharedStorage(task, SharedStorage.downloads);
  • 点击暂停后,再点击恢复可以继续下载。点击取消后,再点击恢复无法继续下载。

示例2:上传

dart 复制代码
/// define the multi-part upload task (subset of parameters shown)
final task = UploadTask(
        url: 'https://myserver.com/uploads',
        filename: 'myData.txt',
        fields: {'datafield': 'value'},
        fileField: 'myFile', 
        updates: Updates.statusAndProgress // request status and progress updates
);

// Start upload, and wait for result. Show progress and status changes
// while uploading
final result = await FileDownloader().upload(task,
  onProgress: (progress) => print('Progress: ${progress * 100}%'),
  onStatus: (status) => print('Status: $status')
);

// Act on result, similar to download

这个没有服务器,没有尝试,上面的是官方例子。

示例3:批量下载

dart 复制代码
final tasks = [task1, task2, task3]; // a list of Download tasks

// download the batch
final result = await FileDownloader().downloadBatch(tasks,
  batchProgressCallback: (succeeded, failed) =>
    print('Completed ${succeeded + failed} out of ${tasks.length}, $failed failed')
);

使用DownloadTask会返回一个任务,多个任务可以使用downloadBatch来进行批量下载。

示例4:发起通知

按照官方例子试了一下,一直没有发起通知。

我这里的问题是app没有通知权限,在设置里也无法开启通知。

如果你也没有成功的话,可以使用flutter_local_notifications来实现通知功能
Flutter:flutter_local_notifications------消息推送的学习

示例5:打开下载文件

dart 复制代码
  _downloadFile() async {
    task = DownloadTask(
        url:
        'https://ppt.1ppt.com/uploads/soft/2307/1-230H1092638.zip', // 下载地址
        // urlQueryParameters: {'q': 'pizza'},  // 请求参数
        filename: '1-230H1092638.zip', // 文件名
        //headers: {'myHeader': 'value'},  请求头
        directory: 'my_sub_directory', // 文件存储目录
        baseDirectory: BaseDirectory.applicationSupport,
        updates: Updates.statusAndProgress, // 更新任务状态和下载进度
        requiresWiFi: true, // 使用wifi
        retries: 5, // 下载的重试次数
        allowPause: true, // 运行暂停
        metaData: 'data for me' // 元数据,可以存储一些对于下载任务有用的信息,方便后续相关操作
    );
    // 监听下载
    final result =
    await FileDownloader().download(task, onProgress: (progress) {
      setState(() {
        this.progress = progress;
      });
    }, onStatus: (states) async{
      String msg = '';
      if (states == TaskStatus.complete) {
        msg = '下载完成';
        await FileDownloader().openFile(task: task);
        print("路径:${await task.filePath()}");
      } else if (states == TaskStatus.canceled) {
        msg = '已取消';
        setState(() {
          progress = 0;
        });
      } else if (states == TaskStatus.paused) {
        msg = '已暂停';
      } else if (states == TaskStatus.running) {
        msg = '下载中...';
      } else {
        msg = '下载失败';
      }
      setState(() {
        taskStatus = msg;
      });
    });

  }

注意:

  • 必须要添加 baseDirectory: BaseDirectory.applicationSupport,,否则是无法打开文件的
  • 如果要打开文件,那么就不能使用FileDownloader().moveToSharedStorage(task, SharedStorage.downloads);移动文件,会导致找不到文件进而打不开。另外打开文件时会调用你手机里有的应用程序打开,我试了一下图片、mp4下载完成后是可以直接打开的,但是zip这样的文件是无法直接打开的,这时会让你选择你手机里的应用来打开。

遇到的问题

这是因为background_downloader要求最小的sdk版本是24,而Flutter会自动设置minSdkVersion为16(Android 4.1),在你的Flutter项目的android/app/build.gradle文件中,将minSdkVersion更改为24或更高的版本。然后运行flutter clean清理项目,并重新构建你的应用程序。

从flutter仓库找到了该问题的解决方案:https://github.com/flutter/flutter/issues/119247

android / app/build.gradle文件中添加

dart 复制代码
configurations.all {
    resolutionStrategy {
        eachDependency {
            if ((requested.group == "org.jetbrains.kotlin") && (requested.name.startsWith("kotlin-stdlib"))) {
                useVersion("1.8.0")
            }
        }
    }
}
相关推荐
微祎_8 小时前
Flutter for OpenHarmony:单词迷宫一款基于 Flutter 构建的手势驱动字母拼词游戏,通过滑动手指连接字母路径来组成单词。
flutter·游戏
ujainu8 小时前
护眼又美观:Flutter + OpenHarmony 鸿蒙记事本一键切换夜间模式(四)
android·flutter·harmonyos
ujainu8 小时前
让笔记触手可及:为 Flutter + OpenHarmony 鸿蒙记事本添加实时搜索(二)
笔记·flutter·openharmony
一只大侠的侠8 小时前
Flutter开源鸿蒙跨平台训练营 Day 13从零开发注册页面
flutter·华为·harmonyos
一只大侠的侠8 小时前
Flutter开源鸿蒙跨平台训练营 Day19自定义 useFormik 实现高性能表单处理
flutter·开源·harmonyos
恋猫de小郭10 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
一只大侠的侠14 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
renke336418 小时前
Flutter for OpenHarmony:色彩捕手——基于HSL色轮与感知色差的交互式色觉训练系统
flutter
子春一20 小时前
Flutter for OpenHarmony:构建一个 Flutter 四色猜谜游戏,深入解析密码逻辑、反馈算法与经典益智游戏重构
算法·flutter·游戏
铅笔侠_小龙虾20 小时前
Flutter 实战: 计算器
开发语言·javascript·flutter