Android 11下react-native-fs保存文件到公共Download目录权限问题咨询
Android 11 React Native 公共Download目录存储适配方案
问题根因
你遇到的ENOENT: open failed: EACCES (Permission denied)报错是Android 11及以上版本作用域存储限制导致的:
- 从Android 11开始,系统默认强制开启作用域存储,普通应用默认无法直接通过绝对路径读写
/storage/emulated/0/Download这类公共目录的文件 - 直接读写公共目录绝对路径的权限仅授予申请了
MANAGE_EXTERNAL_STORAGE权限的应用,而该权限仅对文件管理器、杀毒软件等特定类型应用开放,普通应用申请无法通过谷歌Play审核
可行实现方案(无需申请MANAGE_EXTERNAL_STORAGE权限)
方案1:使用适配作用域存储的第三方库(推荐)
推荐使用react-native-file-access库,该库内置了Android MediaStore API适配,可直接将文件写入公共Download目录,所有应用均可访问,无需高危权限。
适配后代码示例:
import { FileSystem, AndroidMimeType } from 'react-native-file-access'; // 构造文件参数 const fileName = `${dataBezeichnung}.${data.dateityp}`; const mimeType = data.dateityp === 'pdf' ? AndroidMimeType.PDF : AndroidMimeType.EXCEL; // 写入公共Download目录 FileSystem.writeFileToMediaStore( meThis.state.dateiBase64, fileName, 'download', // 指定写入Download目录 mimeType, 'base64' ).then(() => { console.log('文件下载成功!'); Functions.toast("成功", "下载成功 \n\n文件:\n" + fileName + "\n\n已成功保存到您的设备", 10000); }).catch((err) => { console.log(err.message); Functions.toast("警告", "无法下载文件,请检查存储权限是否正常开启", 10000); });
配套配置要求
在android/app/src/main/AndroidManifest.xml中添加如下权限配置即可:
- Android 13以下读取媒体文件权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> - Android 10以下写入存储权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
方案2:基于现有react-native-fs改造
如果要继续使用react-native-fs,可先将文件写入应用私有目录,再调用系统原生的MediaStore接口将文件复制到公共Download目录,需要简单封装少量原生Android代码,逻辑如下:
- 先将base64内容写入应用私有下载目录:
RNFS.DocumentDirectoryPath + '/' + fileName - 调用原生方法,通过MediaStore创建公共Download目录的文件记录,获取输出流
- 将私有目录的文件内容写入输出流即可完成公共目录存储
跨应用编辑回传适配
文件写入公共Download目录后,其他应用只要具备正常的存储权限即可读取、编辑,你方App后续要读取修改后的文件时,可通过两种方式实现:
- 调用系统文件选择器让用户主动选择修改后的文件,拿到授权后即可读取内容
- 通过MediaStore按文件名查询你之前写入的文件,获取uri后读取内容
内容的提问来源于stack exchange,提问作者Benq
相关产品推荐
相关产品推荐

