Flutter写入PDF报FileSystemException Operation not permitted错误求解
问题根因
- 安卓分区存储适配问题:Android 10及以上系统默认启用分区存储,普通存储权限仅允许应用访问图片、视频、音频等媒体类文件,PDF、DOC等非媒体文件无法通过普通存储权限写入公共存储目录,这也是你写入图片正常、写入PDF失败的核心原因。
- 代码逻辑存在缺陷:
- 创建
File对象时仅传入文件名后缀.pdf,未指定正确的存储路径,无法匹配你要写入的目标路径 - 权限被拒绝后仅触发请求,没有监听请求结果,用户同意权限后不会继续执行写入逻辑
- 目标路径
DCIM/docs不属于系统规范的非媒体文件存储目录,高版本安卓会禁止写入
- 创建
解决步骤
- 适配安卓存储权限配置
在项目android/app/src/main/AndroidManifest.xml中补充权限和兼容配置:
<!-- 基础存储权限,安卓10及以下生效 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <!-- 安卓11及以上访问非媒体公共文件需要的权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <application <!-- 安卓10兼容配置 --> android:requestLegacyExternalStorage="true" ...> </application>
- 修复写入逻辑
你需要配合path_provider、device_info_plus包处理路径和版本判断,修正后的代码示例:
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; Future<File?> createDocFile(Uint8List fileData, String type) async { bool hasPermission = false; // 分安卓版本判断权限 if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 30) { hasPermission = await Permission.manageExternalStorage.isGranted; if (!hasPermission) { await Permission.manageExternalStorage.request(); hasPermission = await Permission.manageExternalStorage.isGranted; } } else { hasPermission = await Permission.storage.isGranted; if (!hasPermission) { await Permission.storage.request(); hasPermission = await Permission.storage.isGranted; } } } else { // iOS权限逻辑可根据需求自行补充 hasPermission = await Permission.storage.isGranted; } if (!hasPermission) { Url.toastShow("存储权限不足,无法保存文件"); return null; } // 获取合规的存储目录,优先选公共Documents目录 Directory? saveDir; if (Platform.isAndroid) { saveDir = Directory('/storage/emulated/0/Documents/'); } else { saveDir = await getApplicationDocumentsDirectory(); } // 目录不存在则创建 if (!await saveDir.exists()) { await saveDir.create(recursive: true); } // 生成完整文件路径,创建文件对象 final savePath = "${saveDir.path}/myPdf.pdf"; File targetFile = File(savePath); // 写入文件 await targetFile.writeAsBytes(fileData); print("PDF保存路径:$savePath"); Url.toastShow("PDF saved in device", Colors.green); return targetFile; }
- 额外适配建议
如果该PDF不需要让用户在系统文件管理器中直接访问,优先写入应用专属目录,不需要申请任何存储权限,兼容性最好,应用专属目录可以通过getApplicationSupportDirectory()方法直接获取。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

