Expo React Native FileSystem无法在设备保存文件求助
Expo React Native FileSystem 文件保存失败 & CreateDownloadResumable 错误解决方案
一、搞定downloadAsync存不了文件的问题
你代码里踩了几个常见坑,直接导致文件存不上:
- 目录创建没等完成就下载
你用.then()处理目录检查,但没等makeDirectoryAsync执行完就跑downloadAsync,这时候目录可能还没建好,下载路径直接无效。改成异步等待就行:
const downloadFile = async (url) => { try { console.log("Started"); setLoadingModal(true) console.log(url); const fileName = url?.split('/').pop(); // 用pop()更简洁获取文件名 const savePath = `${FileSystem.documentDirectory}FirstOG/`; // 先等目录检查+创建完成 const { exists } = await FileSystem.getInfoAsync(savePath); if (!exists) { console.log("Creating directory..."); // 加intermediates: true确保父目录不存在时也能创建 await FileSystem.makeDirectoryAsync(savePath, { intermediates: true }); } const downloadResult = await FileSystem.downloadAsync( url, `${savePath}${fileName}` ); console.log("Download result:", downloadResult); console.log(`File saved to ${downloadResult.uri}`); // 先验证文件真的存在不 const fileCheck = await FileSystem.getInfoAsync(downloadResult.uri); console.log("File exists post-download:", fileCheck.exists); // 别用Linking.openURL打开私有目录文件,用expo-file-viewer更靠谱 // 先装依赖:npm install expo-file-viewer // import * as FileViewer from 'expo-file-viewer'; // await FileViewer.open(downloadResult.uri); } catch (error) { console.error('Download error:', error); } finally { setLoadingModal(false); } };
- 权限没配到位
- iOS:必须在
app.json里加相册写入权限描述,不然系统直接拒:
{ "expo": { "ios": { "infoPlist": { "NSPhotoLibraryAddUsageDescription": "需要访问相册保存下载的文件" } } } }
- Android:13+要申请媒体库权限,提前用expo-permissions申请:
import * as Permissions from 'expo-permissions'; const checkPermissions = async () => { const { status } = await Permissions.askAsync(Permissions.MEDIA_LIBRARY); return status === 'granted'; }; // 下载前先查权限 const hasPermission = await checkPermissions(); if (!hasPermission) { alert("得给文件访问权限才能保存"); return; }
- 私有目录看不到文件
FileSystem.documentDirectory是App的私有目录,设备文件管理器里找不到!要让用户能看到,得把文件复制到公共目录(比如相册):
// 装expo-media-library:npm install expo-media-library import * as MediaLibrary from 'expo-media-library'; const saveToPublicAlbum = async (fileUri, fileName) => { const { status } = await MediaLibrary.requestPermissionsAsync(); if (status === 'granted') { const asset = await MediaLibrary.createAssetAsync(fileUri); await MediaLibrary.createAlbumAsync('MyDownloads', asset, false); alert("文件已经存到相册的MyDownloads文件夹啦"); } }; // 下载成功后调用这个方法 await saveToPublicAlbum(downloadResult.uri, fileName);
二、Fix CreateDownloadResumable的uuidv4错误
这个错是expo-modules-core版本不兼容或者没装对导致的,按下面步骤来:
- 升级
expo-modules-core到最新版:
npm install expo-modules-core@latest # yarn的话:yarn add expo-modules-core@latest
- 如果还是不行,手动导入uuid传进去:
// 先装uuid:npm install uuid import { v4 as uuidv4 } from 'uuid'; // 创建可恢复下载时手动传uuid const downloadResumable = FileSystem.createDownloadResumable( url, `${savePath}${fileName}`, {}, (progress) => console.log(progress), uuidv4() // 手动生成uuid传进去 );
- 确保你的Expo SDK版本和
expo-modules-core兼容,比如SDK 49+需要expo-modules-core>=1.5.0
额外提醒
- 别用模拟器测缓存问题,拿真实设备测更准
- 先确认你要下载的URL能直接在浏览器打开,有没有跨域或者防盗链限制
- Android 10+如果还是有问题,在
app.json的android配置里加:
"android": { "requestLegacyExternalStorage": true }
内容的提问来源于stack exchange,提问作者Soludo Adigwerex
相关产品推荐
相关产品推荐

