Expo本地Assets图片保存至Android设备:自定义文件夹选择问题
解决Expo SDK47 Android保存Assets图片到用户指定文件夹的问题
问题根源
- Dev环境Asset URI限制:
Asset.fromModule().uri在开发模式下返回本地HTTP服务器地址(如你报错中的http://192.168.1.13:8081/...),FileSystem.copyAsync无法直接读取HTTP资源,必须先将Asset下载到本地文件系统。 - 文件夹选择API误用:
DocumentPicker.getDocumentAsync()用于选择文件,要选择目标文件夹需使用DocumentPicker.getDirectoryAsync()。 - 权限缺失:Android需要外部存储写入权限才能将文件保存到用户指定目录。
解决方案代码
import * as FileSystem from 'expo-file-system'; import * as DocumentPicker from 'expo-document-picker'; import * as Permissions from 'expo-permissions'; import { Asset } from 'expo-asset'; const saveImageToSelectedFolder = async () => { try { // 1. 申请外部存储权限 const { status } = await Permissions.askAsync(Permissions.WRITE_EXTERNAL_STORAGE); if (status !== 'granted') { alert('需要授予存储权限才能保存图片'); return; } // 2. 将Asset下载到本地缓存(解决HTTP地址不可读问题) const asset = Asset.fromModule(require('../../../assets/images/motivational/30.jpg')); await asset.downloadAsync(); const localAssetUri = asset.localUri || asset.uri; // 3. 让用户选择目标文件夹 const dirResult = await DocumentPicker.getDirectoryAsync({ mode: 'open' }); if (dirResult.canceled) { alert('已取消选择文件夹'); return; } const targetDirUri = dirResult.uri; // 4. 拼接目标文件路径并复制 const targetFilePath = `${targetDirUri}/imageName.jpg`; await FileSystem.copyAsync({ from: localAssetUri, to: targetFilePath }); alert('图片保存成功'); // 可选:清理缓存的临时文件 await FileSystem.deleteAsync(localAssetUri); } catch (error) { console.error('保存失败:', error); alert('保存图片失败,请重试'); } };
关键说明
- Asset本地缓存:
asset.downloadAsync()会将远程(开发模式)或打包后的Asset文件下载到Expo缓存目录,生成可被FileSystem直接读取的本地URI。 - 文件夹选择:
getDirectoryAsync()是Expo官方支持的文件夹选择API,返回用户选中的文件夹URI。 - 权限处理:必须先申请
WRITE_EXTERNAL_STORAGE权限,否则Android系统会拒绝写入外部存储操作。 - 生产环境兼容:打包成APK后,
Asset.fromModule().uri会自动转为本地文件路径,downloadAsync()依然兼容,无需额外修改代码。
内容的提问来源于stack exchange,提问作者GOXR3PLUS
相关产品推荐
相关产品推荐

