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 从网上下载文件。

谢谢阅读!

相关推荐
码蜂窝编程官方9 分钟前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
gqkmiss9 分钟前
Chrome 浏览器 131 版本开发者工具(DevTools)更新内容
前端·chrome·浏览器·chrome devtools
Summer不秃14 分钟前
Flutter之使用mqtt进行连接和信息传输的使用案例
前端·flutter
旭日猎鹰18 分钟前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter
sunly_19 分钟前
Flutter:AnimatedSwitcher当子元素改变时,触发动画
flutter
AiFlutter21 分钟前
Flutter封装Coap
flutter
Viktor_Ye25 分钟前
高效集成易快报与金蝶应付单的方案
java·前端·数据库
hummhumm27 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
J老熊37 分钟前
JavaFX:简介、使用场景、常见问题及对比其他框架分析
java·开发语言·后端·面试·系统架构·软件工程
AuroraI'ncoding43 分钟前
时间请求参数、响应
java·后端·spring