You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter移动端实现从REST API保存文件至本地?

在Flutter移动端实现API返回文件的下载保存功能

你需要实现的是从API获取文件流并保存到移动端本地存储的功能,以下是具体实现步骤:

1. 添加必要依赖

在pubspec.yaml中添加以下依赖,分别用于网络请求、获取本地路径和权限处理:

dependencies:
  flutter:
    sdk: flutter
  http: ^1.1.0
  path_provider: ^2.1.1
  permission_handler: ^10.2.0

执行flutter pub get安装依赖。

2. 配置存储权限

移动端需要权限才能写入本地存储,分别配置安卓和iOS的权限:

安卓

在android/app/src/main/AndroidManifest.xml中添加权限声明:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Android 13+ 适配更精细的媒体权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

iOS

在ios/Runner/Info.plist中添加权限描述:

<key>NSPhotoLibraryAddUsageDescription</key>
<string>需要访问相册以保存下载的文件</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问相册以保存下载的文件</string>

3. 核心实现代码

结合你的HTTP请求逻辑,实现下载并保存文件的方法:

普通文件下载(小文件)

import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

Future<void> downloadAndSaveFile() async {
  // 申请存储权限
  final permissionStatus = await Permission.storage.request();
  if (!permissionStatus.isGranted) {
    return; // 权限拒绝则终止操作
  }

  // 替换为你的API地址和请求头
  final apiUrl = Uri.parse("你的API接口地址");
  final requestHeaders = {
    "Authorization": "Bearer 你的身份验证Token",
    // 添加其他需要的请求头
  };

  // 发送请求获取文件字节数据
  final response = await http.get(apiUrl, headers: requestHeaders);

  if (response.statusCode == 200) {
    // 获取本地存储路径,可根据需求选择目录
    final storageDir = await getExternalStorageDirectory();
    final savePath = "${storageDir?.path}/downloaded_file.pdf"; // 自定义文件名和格式

    // 写入文件到本地
    final saveFile = File(savePath);
    await saveFile.writeAsBytes(response.bodyBytes);

    print("文件已保存至: $savePath");
    // 此处可添加弹窗提示用户下载完成
  } else {
    print("请求失败,状态码: ${response.statusCode}");
  }
}

流式下载(大文件,避免内存溢出)

如果API返回的是大文件,建议使用流式下载:

Future<void> downloadLargeFile() async {
  final permissionStatus = await Permission.storage.request();
  if (!permissionStatus.isGranted) return;

  final apiUrl = Uri.parse("你的大文件API地址");
  final requestHeaders = {"Authorization": "Bearer 你的身份验证Token"};

  // 发送流式请求
  final request = http.Request("GET", apiUrl);
  request.headers.addAll(requestHeaders);
  final streamedResponse = await request.send();

  if (streamedResponse.statusCode == 200) {
    final storageDir = await getExternalStorageDirectory();
    final savePath = "${storageDir?.path}/large_file.zip";
    final saveFile = File(savePath);
    final fileSink = saveFile.openWrite();

    // 将流数据写入文件
    await streamedResponse.stream.pipe(fileSink);
    await fileSink.close();

    print("大文件下载完成,路径: $savePath");
  } else {
    print("下载失败,状态码: ${streamedResponse.statusCode}");
  }
}

4. 调用方法

在需要触发下载的地方(比如按钮点击事件)调用上述方法即可:

ElevatedButton(
  onPressed: downloadAndSaveFile,
  child: const Text("下载文件"),
)

内容的提问来源于stack exchange,提问作者Kaan Tomruk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 17:06:57