简体   繁体   English

如何获取使用 Flutter 保存文件的 Android 下载路径?

[英]How to get the Android Downloads path for saving files using Flutter?

How to get the visible Android Downloads path for saving files using Flutter?如何获得可见的 Android 使用 Flutter 保存文件的下载路径? Is this possibly because I am running the app in debug mode from android-studio device manager to a physically connected tablet as opposed to an installed app?这可能是因为我在调试模式下运行应用程序,从 android-studio 设备管理器到物理连接的平板电脑,而不是安装的应用程序?

My Flutter app downloads files of any type from an API and I want to save them in the Downloads folder.我的 Flutter 应用程序从 API 下载任何类型的文件,我想将它们保存在下载文件夹中。 This may seem like a simple question but I can't find the file anywhere on my android tablet.这似乎是一个简单的问题,但我在 android 平板电脑的任何地方都找不到该文件。

This code returns /data/user/0/com.myapp/app_flutter/fatsquid.jpg此代码返回/data/user/0/com.myapp/app_flutter/fatsquid.jpg

path_provider: ^2.0.11
import 'package:path_provider/path_provider.dart';
---
Future<String> getFilePath(uniqueFileName) async {
  String path = '';
  Directory dir = await getApplicationDocumentsDirectory();
  path = '${dir.path}/$uniqueFileName';
  return path;
}

My intention is to save the file in a visible directory, preferable the Downloads folder.我的意图是将文件保存在可见目录中,最好是下载文件夹。 I don't need the user to pick a directory, similar to web browsers.我不需要用户选择目录,类似于 web 浏览器。

I am using dio.download to return the file like this我正在使用dio.download像这样返回文件

  Future<void> downloadMobileFile(User user) async {
    log('downloading with mobile function ');
    setState(
      () {
        downloading = true;
        filename = user.downloadFileName;
      },
    );

    bool hasPermission = await _requestWritePermission();
    if (!hasPermission) return;

    String savePath = await getFilePath(user.downloadFileName);

    print(savePath);

    final storage = FlutterSecureStorage();

    String? token = await storage.read(key: 'jwt');

    Dio dio = Dio();

    dio.interceptors.add(LogInterceptor(responseBody: false));

    dio.download(
      user.fileUrl,
      savePath,
      options: Options(
        headers: {HttpHeaders.authorizationHeader: 'Bearer $token'},
      ),
      onReceiveProgress: (rcv, total) {
        setState(
          () {
            received =
                'received: ${rcv.toStringAsFixed(0)} out of total: ${total.toStringAsFixed(0)}';
            progress = ((rcv / total) * 100).toStringAsFixed(0);
          },
        );
        if (progress == '100') {
          setState(
            () {
              isDownloaded = true;
            },
          );
        } else if (double.parse(progress) < 100) {}
      },
      deleteOnError: true,
    ).then(
      (_) {
        print(progress);
        print(isDownloaded);

        setState(
          () {
            if (progress == '100') {
              isDownloaded = true;
            }
            downloading = false;
          },
        );
      },
    );
    // opens the file
    //OpenFile.open("${dir.path}/$fileName", type: 'application/pdf');
  }

  Future<bool> _requestWritePermission() async {
    await Permission.storage.request();
    return await Permission.storage.request().isGranted;
  }

console output from the download function:控制台 output 从下载 function:

[log] downloading with mobile function 
I/flutter (12774): file download path
I/flutter (12774): /data/user/0/com.mydomain/app_flutter/fatsquid.jpg
I/flutter (12774): *** Request ***
I/flutter (12774): uri: https://api.mydomain.com/transcript/download/transcript/file/1
I/flutter (12774): method: GET
I/flutter (12774): responseType: ResponseType.stream
I/flutter (12774): followRedirects: true
I/flutter (12774): connectTimeout: 0
I/flutter (12774): sendTimeout: 0
I/flutter (12774): receiveTimeout: 0
I/flutter (12774): receiveDataWhenStatusError: true
I/flutter (12774): extra: {}
I/flutter (12774): headers:
I/flutter (12774):  authorization: Bearer toosecrettotell
I/flutter (12774): 
I/flutter (12774): *** Response ***
I/flutter (12774): uri: https://api.mydomain.com/transcript/download/transcript/file/1
I/flutter (12774): statusCode: 200
I/flutter (12774): headers:
I/flutter (12774):  content-type: application/octet-stream
I/flutter (12774):  date: Fri, 16 Sep 2022 06:02:40 GMT
I/flutter (12774):  vary: Origin
I/flutter (12774):  content-length: 497741
I/flutter (12774): 
I/flutter (12774): 100
I/flutter (12774): true
D/Surface (12774): Surface::disconnect(this=0x73ae0c8000,api=1)
D/Surface (12774): Surface::disconnect(this=0x73ae0c8000,api=-1)
D/Surface (12774): Surface::disconnect(this=0x7357103000,api=1)
I/GED     (12774): ged_boost_gpu_freq, level 100, eOrigin 2, final_idx 2, oppidx_max 2, oppidx_min 0
V/PhoneWindow(12774): DecorView setVisiblity: visibility = 4, Parent = android.view.ViewRootImpl@c627c36, this = DecorView@f8b8737[MainActivity]

I tried using this code instead but it returned the same directory我尝试使用此代码,但它返回了相同的目录

  Future<String> getFileSavePath(String uniqueFileName) async {
    final Directory? dir = await getExternalStorageDirectory();
    String path = '${dir?.path}/$uniqueFileName';
    print("file download path");
    print(path);
    return path;
  }

My android/app/src/main/AndroidManifest.xml file:我的android/app/src/main/AndroidManifest.xml文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

   <application

When I use a hard coded string path as suggested, I get this error:当我按照建议使用硬编码字符串路径时,出现此错误:

E/flutter (25145): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FileSystemException: Cannot create file, path = '/storage/emulated/0/Download/fatsquid.jpg' (OS Error: Permission denied, errno = 13)

This question has been answered.这个问题已经回答了。 Have you seen Flutter - save file to download folder - downloads_path_provider ?你见过Flutter - 将文件保存到下载文件夹 - downloads_path_provider吗?

path_provider will probably undergo some changes soon, there are some open issues: path_provider 可能很快会发生一些变化,有一些未解决的问题:
https://github.com/flutter/flutter/issues/35783\ As of right now, the best way to get the download path on an Android device is to use: https://github.com/flutter/flutter/issues/35783\截至目前,在 Android 设备上获取下载路径的最佳方法是使用:
/storage/emulated/0/Download/

The issue on https://github.com/flutter/flutter/issues/35783 has been closed without any solution on path_provider package https://github.com/flutter/flutter/issues/35783上的问题已关闭,path_provider package 没有任何解决方案

so you can use:所以你可以使用:

/storage/emulated/0/Download/

and you may make sure to add your permission on manifest.xml file:并且您可以确保在 manifest.xml 文件中添加您的权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM