RNFS无法找到react-native-vision-camera拍摄照片的问题排查
问题现象
在React Native应用中使用react-native-vision-camera@^2.13.5实现拍照功能,照片上传完成后尝试通过react-native-fs@^2.20.0删除本地文件时,iOS和Android双端均报文件不存在错误,具体报错如下:
iOS端报错:[Error: ENOENT: no such file or directory, open '/private/var/mobile/Containers/Data/Application/1BB2256A-ED83-407D-9C76-07431268779B/tmp/ReactNative/CE2FA429-76C8-4BD9-925A-BED09B0B77BB.jpeg']
Android端报错:[Error: File does not exist],对应文件路径格式为:/data/user/0/packagename/cache/mrousavy2423256141715663083.jpg
复现代码
const photo = await camera.current.takePhoto(); // camera: React.RefObject<Camera> const task = storage().ref(<ref>).putFile(photo.path) const result = await task.then(); // Firebase Storage可正常读取并上传照片 RNFS.stat(photo.path) // <-- 报错:The file “CE2FA429-76C8-4BD9-925A-BED09B0B77BB.jpeg” couldn’t be opened because there is no such file. RNFS.unlink(photo.path) // <-- 报错:[Error: ENOENT: no such file or directory, open '/private/var/mobile/Containers/Data/Application/1BB2256A-ED83-407D-9C76-07431268779B/tmp/ReactNative/CE2FA429-76C8-4BD9-925A-BED09B0B77BB.jpeg'] // 路径前拼接file://前缀后仍然无法正常访问 RNFS.unlink(`file://${photo.path}`) RNFS.stat(`file://${photo.path}`)
运行环境
"react-native": "0.68.2", "react-native-fs": "^2.20.0", "react-native-vision-camera": "^2.13.5", "测试设备": "搭载iOS 15.5系统的iPhone 8 Plus"
常见问题解答
1. 该问题是否是因为react-native-fs缺少必要的访问权限导致?
不是权限问题。报错涉及的两个路径都属于应用自身沙箱内部目录:iOS的tmp目录、Android的cache目录,应用本身对这两个目录拥有完整读写权限,不需要额外申请系统权限。报错核心原因是调用删除/查询操作时,文件已经被内部逻辑清理。
2. 为什么Firebase Storage可以正常访问该路径下的照片?
Firebase的putFile方法在调用时会立刻读取对应路径的文件流,此时文件刚拍摄完成还未被清理,所以可以正常读取上传。等上传Promise状态变为完成后,临时文件已经被Vision Camera的内部清理逻辑移除,后续RNFS再访问自然找不到文件。
3. 该路径是否为应用关闭后会自动清理的临时文件夹?
是标准临时目录:
- iOS端的
tmp/ReactNative目录是系统级临时目录,系统会在磁盘空间不足、应用长时间未运行时自动清理该目录下的文件,应用重启时也可能触发清理。 - Android端的
cache目录是应用专属缓存目录,系统同样会在存储空间不足时自动清理该目录内容,用户手动清除应用缓存时也会清空该路径下的文件。
4. 为什么react-native-vision-camera默认将拍摄的媒体文件存储在该路径下?
拍照生成的原始文件默认是临时产物,存缓存目录有两个核心考虑:
- 不需要申请额外存储权限,iOS和Android都允许应用直接读写自身沙箱内的缓存目录,不会触发权限弹窗,用户体验更流畅。
- 避免无意义占用用户永久存储空间,拍摄的照片如果用户没有主动保存到系统相册,就不应该长期残留在用户设备里。
5. 该路径下的媒体文件是否需要手动删除,还是系统会自动清理?
正常场景下不需要手动删除。react-native-vision-camera内部自带临时文件清理逻辑,会在应用切后台、触发新拍摄动作时自动清理历史临时拍摄文件;加上系统层面对临时目录、缓存目录的自动回收机制,不会出现文件长期占用存储空间的问题。
如果需要在上传完成后立刻释放空间,不要直接操作Vision Camera返回的原始临时路径——拿到photo对象后先把文件拷贝到自己可控的沙箱目录(比如RNFS提供的CachesDirectory、DocumentDirectory),用拷贝后的文件路径走上传逻辑,上传完成后直接删除自己拷贝的文件即可,避免和Vision Camera的内部清理逻辑冲突。
内容的提问来源于stack exchange,提问作者Amir-Mousavi

