Flutter 中怎么下载文件

原文链接:How to download files in a flutter. - 原文作者 Dipali Thakare
本文采用意译的方式

本文将演示在 Flutter 应用中,怎么从网上下载文件。我们可以下载任何类型的文件,并将其存储到指定位置。有很多种方法实现,比如很受欢迎的包 flutter download 可以用来实现。然而,我们将会以最简单的方式来演示。

今天,我们将学习怎么将网络上的文件下载下来,并展示一个进度条。

首先,我们需要添加 Flutterdiopermission_handlerpath_provider 到我们的项目,在 pubspec.yaml 文件中添加下面的内容。

yaml 复制代码
  dio: any
  permission_handler: any
  path_provider: any

AndroidManifest.xml 文件中添加读和写的允许:

xml 复制代码
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

并且,在 AndroidManifest.xml 文件中添加 <application> 这个标签:

xml 复制代码
<application
   android:requestLegacyExternalStorage="true"

首先,创建一个 FileDownload.dart 文件。_startDownloading 方法将会创建一个文件,该文件的路径由 _getFilePath 方法返回。在安卓中,我们可以在下载的文件夹中看到这个文件。

dart 复制代码
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';

import 'package:path_provider/path_provider.dart';

class FileDownload {
  Dio dio = Dio();
  bool isSuccess = false;

  void _startDownloading(BuildContext context, final Function okCallback) async {
    String fileName = "Sample.pdf"; // 设定下载文件的名称

    String baseUrl =
        "https://file-examples.com/wp-content/uploads/2017/10/file-example_PDF_1MB.pdf"; // 远程文件路径

    String path = await _getFilePath(fileName); // 获取存储在本地的路径

    try {
      await dio.download(
        baseUrl,
        path,
        onReceiveProgress: (recivedBytes, totalBytes) {
          okCallback(recivedBytes, totalBytes);
        },
        deleteOnError: true,
      ).then((_) {
        isSuccess = true;
      });
    } catch (e) {
      print("Exception$e");
    }

    if (isSuccess) {
      Navigator.pop(context);
    }
  }

  Future<String> _getFilePath(String filename) async {
    Directory? dir;

    try {
      if (Platform.isIOS) {
        dir = await getApplicationDocumentsDirectory(); // 针对 iOS
      } else {
        dir = Directory('/storage/emulated/0/Download/');  // 针对 android
        if (!await dir.exists()) dir = (await getExternalStorageDirectory())!;
      }
    } catch (err) {
      print("Cannot get download folder path $err");
    }
    return "${dir?.path}$filename";
  }
}

下载进度对话框:

下面是进度对话框的代码。当下载一个文件时候,进度对话框会显示,用于展示下载的进度。

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter_downloading_file/download_file.dart';

class DownloadProgressDialog extends StatefulWidget {
  @override
  State<DownloadProgressDialog> createState() => _DownloadProgressDialogState();
}

class _DownloadProgressDialogState extends State<DownloadProgressDialog> {
  double progress = 0.0; // 当前进度

  @override
  void initState() {
    _startDownload(); // 开始下载
    super.initState();
  }

  void _startDownload() {
    FileDownload().startDownloading(context, (recivedBytes, totalBytes) {
      setState(() {
        progress = recivedBytes / totalBytes; // 接收到的字节 / 文件总的字节
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    String downloadingProgress = (progress * 100).toInt().toString();
      return AlertDialog(
        content: Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          margin: const EdgeInsets.symmetric(vertical: 10),
          child: const Text(
            "Downloading",
            style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
          ),
        ),
        LinearProgressIndicator( // 展示当前的下载进度
          value: progress,
          backgroundColor: Colors.grey,
          color: Colors.green,
          minHeight: 10,
        ),
        Align(
          alignment: Alignment.bottomRight,
          child: Text(
            "$downloadingProgress %",
          ),
        )
      ],
    ));
  }
}

在我们的 main.dart 文件中,使用下面的代码

main.dart 文件中,我们已经实现了一个带有下载按钮的简单代码。当点击下载按钮,我们会请求许可。一旦许可被通过,我们将可以下载文件。

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter_downloading_file/dowload_progress.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(MaterialApp(
    theme: ThemeData(
      primarySwatch: Colors.blueGrey,
    ),
    home: const MyHomePage(),
  ));
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    super.key,
  });

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Download file in flutter"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () async { // 点击下载按钮
                  bool result = await _permissionRequest();
                  if (result) { // 可以下载,则展示对话框
                    showDialog(
                        context: context,
                        builder: (dialogcontext) {
                          return DownloadProgressDialog();
                        });
                  } else {
                    print("No permission to read and write.");
                  }
                },
                child: const Text("Download File"))
          ],
        ),
      ),
    );
  }
  
  // 是否允许请求
  static Future<bool> _permissionRequest() async {
    PermissionStatus result;
    result = await Permission.storage.request();
    if (result.isGranted) {
      return true;
    } else {
      return false;
    }
  }
}

一旦文件被下载了,它可以被使用 open_filex包打开。这个包允许我们打开任何类型的文件。

输出:

初始化下载按钮

当触发下载按钮,则调出文件下载进度的弹窗

希望这篇文件能够帮到你们用 flutter 从网上下载文件。

谢谢阅读!

相关推荐
啦啦右一28 分钟前
Spring Boot | (一)Spring开发环境构建
spring boot·后端·spring
森屿Serien29 分钟前
Spring Boot常用注解
java·spring boot·后端
轻口味1 小时前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王2 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发2 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
旭东怪3 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
∝请叫*我简单先生3 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl