Flutter 文件创建错误:(操作系统错误:不允许操作,errno = 1)

Nis*_*n S 7 dart flutter

我正在尝试将 Excel 文件保存到本地存储,但在创建文件时遇到此错误。我正在使用物理设备进行调试。仅当设备具有外部 SD 卡并配置为内部存储时才有效。但是,当我使用 SD 卡(配置为便携式存储)在不同的设备(物理设备)上运行该应用程序时,它不起作用,并且出现以下错误。

错误

[ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: FileSystemException: Creation failed, path = '/storage/emulated/0/Traders' (OS Error: Operation not permitted, errno = 1)
E/flutter (15532): #0      _Directory.create.<anonymous closure> (dart:io/directory_impl.dart:117:11)
E/flutter (15532): #1      _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter (15532): #2      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter (15532): #3      _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
E/flutter (15532): #4      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
E/flutter (15532): #5      Future._propagateToListeners (dart:async/future_impl.dart:733:32)
E/flutter (15532): #6      Future._completeWithValue (dart:async/future_impl.dart:539:5)
E/flutter (15532): #7      Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:577:7)
E/flutter (15532): #8      _rootRun (dart:async/zone.dart:1354:13)
E/flutter (15532): #9      _CustomZone.run (dart:async/zone.dart:1258:19)
E/flutter (15532): #10     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
E/flutter (15532): #11     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
E/flutter (15532): #12     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (15532): #13     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
E/flutter (15532): 
Run Code Online (Sandbox Code Playgroud)

我的代码

import 'dart:io' as IO;

IO.Directory dir = await getExternalStorageDirectory();
    String outputFile = "report"+DateFormat('dd-MM-yyyy hh:mm:ss').format(DateTime.now())+".xls";
    if (await Permission.storage.request().isGranted) {

      if (!IO.Directory('${dir.parent.parent.parent.parent.parent.path}/Traders/Reports').existsSync())
        await IO.Directory('${dir.parent.parent.parent.parent.path}/Traders/Reports').create(recursive: true);
      final file = IO.File(join('${dir.parent.parent.parent.parent.path}/Traders/Reports',outputFile));
      await file.writeAsBytes(excel.encode()).then((value) {
        if(IO.Platform.isAndroid||IO.Platform.isIOS)
          OpenFile.open('${dir.parent.parent.parent.parent.path}/Traders/Reports/$outputFile');
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("File Saved !")));
      }).catchError((e){
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Error Saving File !")));
      });
    }else{
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Error:Permission denied.Grant storage permission to save file."),action: SnackBarAction(label: 'Grant',onPressed: ()async{
        await Permission.storage.request();
      },),));
    }
Run Code Online (Sandbox Code Playgroud)

AndroidMalifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)

Pro*_*ude 6

(注:这个包 ext_storage 1.0.3 与当前版本的 Flutter 不兼容。(2023 年 5 月) 上面代码比较乱,可以使用这个包直接获取 Home 路径。( /storage/emulated/0)

然后你可以简单地这样做

var path = await ExtStorage.getExternalStorageDirectory();
final file = await File(path+'/Traders/Report').create(recursive: true);
file.writeAsStringSync("Hello I'm writting a stackoverflow answer into you");

Run Code Online (Sandbox Code Playgroud)

或者

我知道这个包不是 null 安全的。所以在这种情况下我提供本机代码。

一些 dart 文件,您需要路径

exportPath = await channel.invokeMethod('getExternalStorageDirectory'); // Call native code like this in your dart file
Run Code Online (Sandbox Code Playgroud)

然后实施这个

转到“android->app->src->main->kotlin->....你的应用程序名称->MainActivity.kt”。

Add this


class MainActivity : FlutterFragmentActivity() {
    private val channel = "externalStorage";

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler { call, result ->
            when (call.method) {
                "getExternalStorageDirectory" ->
                    result.success(Environment.getExternalStorageDirectory().toString())
                "getExternalStoragePublicDirectory" -> {
                    val type = call.argument<String>("type")
                    result.success(Environment.getExternalStoragePublicDirectory(type).toString())
                }
                else -> result.notImplemented()
            }
        }

    }

}
Run Code Online (Sandbox Code Playgroud)