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

Flutter Dio真机无下载文件但模拟器正常问题求助

解决Flutter Dio在安卓真机下载文件到Download目录不显示的问题

问题原因分析

你遇到的问题核心出在三点:

  • Android 10(API 29)及以上存储权限机制变更,直接写入公共Download目录的权限逻辑发生了变化
  • 文件下载完成后未触发系统媒体扫描,导致文件管理器无法立即识别到新文件
  • 硬编码路径/storage/emulated/0/Download在部分真机上存在兼容性问题

解决方案步骤

1. 替换硬编码路径,用官方API获取公共Download目录

不要直接写死路径,通过path_provider库获取标准的公共下载目录,确保在不同设备上都能正确定位。

先在pubspec.yaml添加依赖:

dependencies:
  path_provider: ^2.1.1

2. 适配Android 10+的存储权限

Android 10及以上,针对公共媒体目录的写入,需要在AndroidManifest.xml中添加兼容配置;Android 13+则需要申请MANAGE_EXTERNAL_STORAGE权限(需引导用户去系统设置开启)。

在android/app/src/main/AndroidManifest.xml的<application>标签内添加:

android:requestLegacyExternalStorage="true"

3. 下载完成后触发媒体扫描

文件写入公共目录后,必须通知系统媒体库扫描该文件,才能让文件管理器显示出来。可以借助media_scanner库实现。

添加media_scanner依赖:

dependencies:
  media_scanner: ^1.0.1

修改后的完整代码

onPressed: () async {
  // 适配不同Android版本的权限
  Permission permission;
  if (Platform.isAndroid) {
    final androidInfo = await DeviceInfoPlugin().androidInfo;
    if (androidInfo.version.sdkInt >= 33) {
      permission = Permission.manageExternalStorage;
    } else {
      permission = Permission.storage;
    }
  } else {
    permission = Permission.storage;
  }

  PermissionStatus status = await permission.request();

  if (status.isGranted) {
    // 获取公共Download目录
    Directory? dir;
    if (Platform.isAndroid) {
      dir = await getExternalStoragePublicDirectory(DirectoryDownloads);
    } else if (Platform.isIOS) {
      dir = await getApplicationDocumentsDirectory();
    }

    if (dir == null) {
      print("无法获取下载目录");
      return;
    }

    String savename = "file.gpx";
    String savePath = "${dir.path}/$savename";
    print(savePath);

    try {
      await Dio().download(fileurl, savePath,
          onReceiveProgress: (received, total) {
        if (total != -1) {
          print("${(received / total * 100).toStringAsFixed(0)}%");
        }
      });
      print("File is saved to download folder.");

      // 触发媒体扫描,让文件在文件管理器中显示
      if (Platform.isAndroid) {
        await MediaScanner.loadMedia(savePath);
      }
    } on DioError catch (e) {
      print(e.message);
      print(e.response?.data); // 打印更详细的错误信息便于排查
    }
  } else {
    print("No permission to read and write.");
    // Android 13+权限被拒时,引导用户去设置开启
    if (Platform.isAndroid && await DeviceInfoPlugin().androidInfo.version.sdkInt >= 33) {
      await openAppSettings();
    }
  }
}

额外注意事项

  • 测试时可先通过adb shell或应用内读取文件的方式,确认文件是否真的下载成功,避免误以为下载失败
  • Android 14及后续版本可能有更严格的权限限制,需及时跟进官方文档更新
  • 如果不需要在应用外部访问文件,建议使用应用专属目录,无需特殊权限,路径可通过getExternalStorageDirectory()获取

内容的提问来源于stack exchange,提问作者Jorgen Timarey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:45:30