React Native Camera拍摄图片后无法读取文件上传AWS S3的问题
问题分析与解决方案
首先,咱们来拆解下你遇到的Error: file not exists问题,主要原因和解决办法如下:
核心原因
- 路径格式不兼容
react-native-camera的takePictureAsync返回的uri在iOS和Android上的格式存在差异:
- iOS上通常是
file://开头的URI,但RNFetchBlob的fs.readFile并不需要这个前缀,直接传入会导致路径识别错误; - Android上的缓存路径属于应用内部存储范畴,RNFetchBlob如果没有正确识别路径格式,也会出现找不到文件的情况。
- 文件写入延迟(概率较低)
刚拍摄完成的图片可能还在异步写入缓存文件夹,此时立即读取可能会碰到文件尚未完全写入的情况,但这种情况出现的概率远低于路径格式问题。
解决方案
方案1:直接使用返回的base64数据(最简便)
你已经在拍照选项里设置了base64: true,takePictureAsync会直接返回图片的base64编码,完全不需要再去读取本地文件,这样能彻底绕开路径问题:
修改你的代码如下:
takePicture = async function () { if (this.camera) { const options = {base64: true}; const data = await this.camera.takePictureAsync(options); console.log(data.uri); // 直接传入base64数据,不用读文件 uploadPictureToS3(data.base64, "image.jpg"); } }; function uploadPictureToS3(base64Data, key) { const buffer = new Buffer(base64Data, 'base64'); Storage.put(key, buffer, { contentType: "image/jpeg" }) .then(r => { console.log(r); }) .catch(e => { console.error(e); }); }
方案2:修复RNFetchBlob的路径识别问题
如果你坚持要读取本地文件,需要针对不同平台处理路径格式:
import { Platform } from 'react-native'; function readFile(fileUri) { // 处理iOS的file://前缀,Android路径直接使用 const filePath = Platform.OS === 'ios' ? fileUri.replace('file://', '') : fileUri; return RNFetchBlob.fs.readFile(filePath, 'base64').then(data => new Buffer(data, 'base64')); }
另外,Android平台上需要确保应用有文件读取权限,在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
为什么无法直接读取缓存文件夹的图片?
react-native-camera拍摄的图片默认存在应用的临时缓存目录,这个目录的路径格式和RNFetchBlob期望的路径格式不匹配,再加上不同平台的文件系统规则差异(比如iOS的沙箱机制、Android的存储权限限制),直接使用返回的uri就会出现找不到文件的情况。而用拍照时直接返回的base64数据,相当于跳过了本地文件读取的步骤,自然就不会有这个问题。
内容的提问来源于stack exchange,提问作者ppgcc74
相关产品推荐
相关产品推荐

