You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo中用expo-file-system移文件遇WRITE_EXTERNAL_STORAGE权限问题求助

解决Expo中expo-file-system文件移动的WRITE_EXTERNAL_STORAGE权限问题

一、修正app.json权限配置

你已在android.permissions中添加存储权限,但需确保配置完整且适配Android版本:

  1. 完善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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:20:12