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

Posted

技术标签:

【中文标题】Flutter:在外部存储路径上创建目录 - 路径提供程序 getExternalStorageDirectory()【英文标题】:Flutter : Create directory on external storage path - path provider getExternalStorageDirectory() 【发布时间】:2019-06-20 02:39:18 【问题描述】:

我正在创建一个颤振应用程序,我想在其中下载图像并将其存储到外部存储(不是文档目录),以便任何照片库应用程序都可以查看它。 我正在使用以下代码创建目录

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

它给了我以下错误:

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

我已在清单文件中设置权限,并使用以下代码获取运行时权限

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);
  
);

我已经在设置中验证了该应用已获得权限,也正如这里的一些答案所建议的那样,我还尝试手动从设置应用授予权限,但没有成功。

【问题讨论】:

【参考方案1】:

您需要在使用 getExternalStorageDirectory 保存文件之前请求权限。

将此添加到 androidmanifest.xml:

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

然后使用permission_handler包获取Storage权限:

https://pub.dev/packages/permission_handler

如果你在模拟器中运行,getExternalStorageDirectory 返回:

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

如果您只需要外部目录在其下创建目录,则只需使用:

/storage/emulated/0/

你可以在这个文件夹下创建一个目录,这样他们的用户就可以打开文件了。

【讨论】:

嘿,这对 android 10 设备抛出错误 未处理异常:FileSystemException:创建失败,路径 = '/storage/emulated/0/app_name'(操作系统错误:不允许操作,errno = 1)【参考方案2】:

下面的代码在我的应用程序中运行良好,可以使用 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;

命名空间

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';

希望对你有帮助

【讨论】:

视频怎么样?【参考方案3】:

这是一个可操作的 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;
    
  


【讨论】:

以上是关于Flutter:在外部存储路径上创建目录 - 路径提供程序 getExternalStorageDirectory()的主要内容,如果未能解决你的问题,请参考以下文章

Android Oreo (API 26) - 在外部存储中创建目录

无法在外部 tomcat 上部署 Spring Boot 应用程序

如何获得一个数组/列表,其中填充了我在 Flutter 中作为资产加载的所有图像路径?

在外部存储 Flyway 元数据表

在外部 Tomcat 服务器上运行的 Springboot 在除 index.html 之外的所有内容上都会出现错误 404

安卓 11 |范围存储实施