Expo中用expo-file-system移文件遇WRITE_EXTERNAL_STORAGE权限问题求助
解决Expo中expo-file-system文件移动的WRITE_EXTERNAL_STORAGE权限问题
一、修正app.json权限配置
你已在android.permissions中添加存储权限,但需确保配置完整且适配Android版本:
- 完善expo-media-library插件配置(若代码中用到媒体库相关方法,比如获取相册):
{ "expo": { ... "plugins": [ [ "expo-media-library", { "photosPermission": "Allow $(PRODUCT_NAME) to access your photos.", "savePhotosPermission": "Allow $(PRODUCT_NAME) to save photos.", "isAccessMediaLocationEnabled": true, "android": { "writeExternalStoragePermission": "Allow $(PRODUCT_NAME) to modify your media files." } } ] ], ... "android": { // 基础存储权限 "permissions": ["WRITE_EXTERNAL_STORAGE", "READ_EXTERNAL_STORAGE"], // Android 11+ 需要操作全量文件时,添加MANAGE_EXTERNAL_STORAGE "permissions": ["WRITE_EXTERNAL_STORAGE", "READ_EXTERNAL_STORAGE", "MANAGE_EXTERNAL_STORAGE"], ... } } }
注意:确保app.json的JSON语法正确,避免未闭合的括号。
二、代码中主动请求权限
仅配置app.json无法自动获取权限,必须在代码中主动向用户申请:
1. 若用到expo-media-library(对应错误中的"Failed to get albums")
如果代码里调用了MediaLibrary.getAlbums()等方法,先请求媒体库权限:
import * as MediaLibrary from 'expo-media-library'; import * as FileSystem from 'expo-file-system'; const requestMediaPermissions = async () => { const { status } = await MediaLibrary.requestPermissionsAsync(); if (status !== 'granted') { alert('需要授予媒体库权限才能操作'); return false; } return true; }; // 文件移动逻辑 const moveFile = async () => { const hasPermission = await requestMediaPermissions(); if (!hasPermission) return; try { await FileSystem.moveAsync({ from: '原文件完整路径', to: '目标文件完整路径' }); console.log('文件移动成功'); } catch (err) { console.error('移动失败:', err); } };
2. 仅使用expo-file-system操作文件
若操作非媒体库文件,请求存储权限(注意:expo-permissions已弃用,推荐用对应模块的权限方法):
import * as FileSystem from 'expo-file-system'; import * as Permissions from 'expo-permissions'; // SDK 44+ 建议替换为expo-media-library或expo-document-picker的权限请求 const requestStoragePermissions = async () => { const { status } = await Permissions.askAsync(Permissions.WRITE_EXTERNAL_STORAGE); if (status !== 'granted') { alert('需要授予存储权限才能移动文件'); return false; } return true; }; const moveFile = async () => { const hasPermission = await requestStoragePermissions(); if (!hasPermission) return; try { await FileSystem.moveAsync({ from: `${FileSystem.documentDirectory}test.txt`, to: '/storage/emulated/0/Download/test.txt' }); } catch (err) { console.error(err); } };
三、Android 10+ Scoped Storage适配
Android 10(API 29)及以上启用了Scoped Storage,WRITE_EXTERNAL_STORAGE不再允许访问所有文件:
- 若需操作媒体库之外的文件,Android 11+需添加
MANAGE_EXTERNAL_STORAGE权限,并引导用户到应用设置开启“所有文件访问权限”:
import * as IntentLauncher from 'expo-intent-launcher'; const openAppSettings = async () => { await IntentLauncher.startActivityAsync(IntentLauncher.ACTION_APPLICATION_DETAILS_SETTINGS, { data: `package:${process.env.EXPO_PUBLIC_APP_ID}` }); }; // 在权限请求失败时调用 if (status !== 'granted') { alert('请在设置中开启所有文件访问权限'); openAppSettings(); }
- 优先使用expo-document-picker让用户选择文件,避免直接操作外部存储路径,适配性更强。
内容的提问来源于stack exchange,提问作者sasame
相关产品推荐
相关产品推荐

