简体   繁体   English

Flutter:在外部存储路径上创建目录 - 路径提供程序 getExternalStorageDirectory()

[英]Flutter : Create directory on external storage path - path provider getExternalStorageDirectory()

I'm creating a flutter app where I want to download and store an image to the external storage (not documents directory) so it can be viewed by any photo gallery app.我正在创建一个 flutter 应用程序,我想在其中下载图像并将其存储到外部存储(不是文档目录),以便任何照片库应用程序都可以查看它。 I'm using the following code to create a directory我正在使用以下代码创建一个目录

var dir = await getExternalStorageDirectory();
  if(!Directory("${dir.path}/myapp").existsSync()){
    Directory("${dir.path}/myapp").createSync(recursive: true);
  }

It's giving me following error:它给我以下错误:

FileSystemException: Creation failed, path = '/storage/emulated/0/myapp' (OS Error: Permission denied, errno = 13)

I have set up permissions in the manifest file and using the following code for runtime permissions我已经在清单文件中设置了权限,并使用以下代码获得运行时权限

List<Permissions> permissions = await Permission.getPermissionStatus([PermissionName.Storage]);
permissions.forEach((p) async {
  if(p.permissionStatus != PermissionStatus.allow){
    final res = await Permission.requestSinglePermission(PermissionName.Storage);
    print(res);
  }
});

I have verified in settings that app has got the permission, also as suggested on some answers here I've also tried giving permission from settings app manually which did not work.我已经在设置中验证了该应用程序已获得许可,也正如此处某些答案所建议的那样,我还尝试手动授予设置应用程序的许可,但没有用。

The below code is working fine in my application to download an image using the url to the external storage下面的代码在我的应用程序中运行良好,可以使用 url 将图像下载到外部存储

Future<bool> downloadImage(String url) async {
  await new Future.delayed(new Duration(seconds: 1));
  bool checkResult =
      await SimplePermissions.checkPermission(Permission.WriteExternalStorage);
  if (!checkResult) {
    var status = await SimplePermissions.requestPermission(
        Permission.WriteExternalStorage);
    if (status == PermissionStatus.authorized) {
      var res = await saveImage(url);
      return res != null;
    }
  } else {
    var res = await saveImage(url);
    return res != null;
  }
  return false;
}

Future<Io.File> saveImage(String url) async {
  try {
    final file = await getImageFromNetwork(url);
    var dir = await getExternalStorageDirectory();
    var testdir =
        await new Io.Directory('${dir.path}/iLearn').create(recursive: true);
    IM.Image image = IM.decodeImage(file.readAsBytesSync());
    return new Io.File(
        '${testdir.path}/${DateTime.now().toUtc().toIso8601String()}.png')
      ..writeAsBytesSync(IM.encodePng(image));
  } catch (e) {
    print(e);
    return null;
  }
}

  Future<Io.File> getImageFromNetwork(String url) async {
  var cacheManager = await CacheManager.getInstance();
  Io.File file = await cacheManager.getFile(url);
  return file;
}

Namespaces命名空间

import 'dart:io' as Io;
import 'package:image/image.dart' as IM;
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:path_provider/path_provider.dart';
import 'package:simple_permissions/simple_permissions.dart';

Hope it helps希望能帮助到你

You need to request permissions before saving a file using getExternalStorageDirectory.您需要在使用 getExternalStorageDirectory 保存文件之前请求权限。

Add this to Androidmanifest.xml:将此添加到 Androidmanifest.xml:

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

Then use the permission_handler package to get Storage permission:然后使用permission_handler包获取Storage权限:

https://pub.dev/packages/permission_handler https://pub.dev/packages/permission_handler

If you are running in the Emulator, getExternalStorageDirectory returns:如果您在模拟器中运行,则 getExternalStorageDirectory 返回:

/storage/emulated/0/Android/data/com.example.myapp/files/

If you just need the external dir to create a directory under it, then just use:如果您只需要外部目录在其下创建目录,则只需使用:

/storage/emulated/0/

You can create a directory under this folder, so they user will be able to open the files.您可以在此文件夹下创建一个目录,以便他们的用户可以打开文件。

For Android 11 and higher, android change his policy so you have add permission at AndroidManifest..对于 Android 11 及更高版本,android 更改其策略,以便您在 AndroidManifest.. 中添加权限。

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

And Also add these two line inside <application......并且还在 <application ......

android:requestLegacyExternalStorage="true"
android:preserveLegacyExternalStorage="true"

here is an operational and 100% Dart code to make things easier :这是一个可操作的 100% Dart 代码,使事情变得更容易:

import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:path/path.dart' as Path;
import 'package:path_provider/path_provider.dart';

///getExternalStoragePublicDirectory
enum extPublicDir {
  Music,
  PodCasts,
  Ringtones,
  Alarms,
  Notifications,
  Pictures,
  Movies,
  Download,
  DCIM,
  Documents,
  Screenshots,
  Audiobooks,
}
/// use in loop or without:
/// generation loop of a creation of the same directory in a list
/// public or shared folders by the Android system
/*
 for (var ext in extPublicDir.values) {

   ExtStorage.createFolderInPublicDir(
     type: ext,  //or without loop : extPublicDir.Download,
     folderName: "folderName",  // folder or folder/subFolder/... to create
   );

 }
*/
/// provided the ability to create folders and files within folders
/// public or shared from the Android system
///
/// /storage/emulated/0/Audiobooks
/// /storage/emulated/0/PodCasts
/// /storage/emulated/0/Ringtones
/// /storage/emulated/0/Alarms
/// /storage/emulated/0/Notifications
/// /storage/emulated/0/Pictures
/// /storage/emulated/0/Movies
/// storage/emulated/0/Download
/// /storage/emulated/0/DCIM
/// /storage/emulated/0/Documents
/// /storage/emulated/0/Screenshots  //Screenshots dropping ?
/// /storage/emulated/0/Music/

class ExtStorage {

  //According to path_provider
  static Future<String> get _directoryPathESD async {
    var directory = await getExternalStorageDirectory();
    if (directory != null) {
      log('directory:${directory.path}');

      return directory.path;
    }
    log('_directoryPathESD==null');

    return '';
  }

  /// create or not, but above all returns the created folder in a public folder
  /// official, folderName = '', only return the public folder: useful for
  /// manage a file at its root
  static Future<String> createFolderInPublicDir({
    required extPublicDir type,
    required String folderName,
  }) async {

    var _appDocDir = await _directoryPathESD;

    log("createFolderInPublicDir:_appDocDir:${_appDocDir.toString()}");

    var values = _appDocDir.split("${Platform.pathSeparator}");
    values.forEach(print);

    var dim = values.length - 4; // Android/Data/package.name/files
    _appDocDir = "";

    for (var i = 0; i < dim; i++) {
      _appDocDir += values[i];
      _appDocDir += "${Platform.pathSeparator}";
    }
    _appDocDir += "${type.toString().split('.').last}${Platform.pathSeparator}";
    _appDocDir += folderName;

    log("createFolderInPublicDir:_appDocDir:$_appDocDir");

    if (await Directory(_appDocDir).exists()) {
      log("createFolderInPublicDir:reTaken:$_appDocDir");

      return _appDocDir;
    } else {
      log("createFolderInPublicDir:toCreate:$_appDocDir");
      //if folder not exists create folder and then return its path
      final _appDocDirNewFolder =
          await Directory(_appDocDir).create(recursive: true);
      final pathNorma = Path.normalize(_appDocDirNewFolder.path);
      log("createFolderInPublicDir:ToCreate:pathNorma:$pathNorma");

      return pathNorma;
    }
  }
}

暂无
暂无

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

相关问题 Nexus 6 Environment.getExternalStorageDirectory() 无法创建目录外部存储 - Nexus 6 Environment.getExternalStorageDirectory() cannot create directory External storage 如何在android中创建外部存储目录,将外部存储路径显示为“storage / emulated / 0”? - How to create directory in external storage in android which show external storage path as “storage/emulated/0”? 外部存储中App自己的目录的路径 - Path to App own directory in External Storage Environment.getExternalStorageDirectory不返回可移动存储的路径 - Environment.getExternalStorageDirectory does not return the path to the removable storage Android 9 无法在 Android 外部公共路径中创建目录(“storage/emulated/0/MyImages”) - Android 9 can't create directory inside Android external public path("storage/emulated/0/MyImages") 通往外部存储的安全途径 - A Safe Path to External Storage Flutter - 获取IOS的外部存储路径以安全存储认证文件 - Flutter - Get external storage path for IOS to store authentication files securely 如何在颤振中显示来自外部存储路径的图像? - How to display images from a external storage path in flutter? 尝试在外部存储上创建文件时访问拒绝的路径 - Access to the path denied when trying to create a file on external storage 如何使用getExternalStorageDirectory()从外部存储读取子目录 - How to read a Subdirectory from External Storage with getExternalStorageDirectory()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM