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

React Native使用Vision Camera+RNFS保存照片失败问题求助

问题

基于react-native-vision-camera开发照片保存功能,使用react-native-fs(RNFS)访问Android文件路径,保存camera的useRef实例拍摄的照片。已获取CAMERA和WRITE_EXTERNAL_STORAGE权限,能正常获取data.path与RNFS.ExternalDirectoryPath,日志显示moveFile和writeFile操作成功,但找不到保存的照片。

代码实现

function Cam(){
    const devices = useCameraDevices()
    const device = devices.back
    const camera = useRef(null)
    const takePhotoOptions = {
        qualityPrioritization: 'speed',
        flash: 'on'
    }
    const captureHandler = async()=>{
        try{
            if (camera.current == null) throw new Error('Camera Ref is Null');
            console.log('Photo taking ....');

            const data = await camera.current.takePhoto(takePhotoOptions)     
       
           await RNFS.moveFile(`/${data.path}`, `${RNFS.ExternalDirectoryPath}/temp.jpg`)
           .then(()=>console.log("Image Moved",`${data.path}`,'-- to --',`${RNFS.ExternalDirectoryPath}`))

            await RNFS.writeFile(`${RNFS.ExternalDirectoryPath}/temp.jpg`, data, 'ascii')
            .then(()=>console.log("Image wrote",`${data.path}`,'-- to --',`${RNFS.ExternalDirectoryPath}`))
        }catch(err){    
            console.log(err)
        }
    }

    return(<>
    {device != null&&<>
        <Button title='Take a Photo' onPress={()=>captureHandler()}/>
        <View style={{ flex: 1 }}>
            <Camera
                ref={camera}
                style={StyleSheet.absoluteFill}
                device={device}
                photo={true}
                isActive={true}
            />
        </View>
    </>}
    </>)
}

日志信息

LOG Photo taking...
LOG  Image Moved /data/user/0/com.camera/cache/mrousavy6998557498651783260.jpg -- to -- /storage/emulated/0/Android/data/com.camera/files
LOG  Image wrote /data/user/0/com.camera/cache/mrousavy6998557498651783260.jpg -- to -- /storage/emulated/0/Android/data/com.camera/files
解决方案

你的代码存在几个关键问题,导致照片无法正常被找到或识别:

  1. 路径错误:data.path本身已是绝对路径,你给它加了前缀/,导致路径变为//data/user/...,属于无效路径。虽然日志返回成功,但实际moveFile操作并未正确执行。
  2. 错误覆盖文件:takePhoto返回的data是包含路径、尺寸等信息的对象,不是图片文件的二进制内容。你在moveFile之后调用writeFile,用ascii编码把这个对象写入文件,直接覆盖了刚移动的有效图片,导致文件变成无效格式。
  3. 媒体库未刷新:即使文件保存成功,Android媒体库不会自动扫描新文件,导致图库无法显示新保存的照片。

修复后的代码

import RNFS from 'react-native-fs';
import { Platform, NativeModules } from 'react-native';

function Cam(){
    const devices = useCameraDevices()
    const device = devices.back
    const camera = useRef(null)
    const takePhotoOptions = {
        qualityPrioritization: 'speed',
        flash: 'on'
    }

    // 触发Android媒体库扫描,让图库能识别新照片
    const scanFile = async (filePath) => {
        if (Platform.OS === 'android') {
            const { MediaScanner } = NativeModules;
            await MediaScanner.scanFile(filePath);
        }
    }

    const captureHandler = async()=>{
        try{
            if (!camera.current) throw new Error('Camera Ref is Null');
            console.log('Photo taking ....');

            const data = await camera.current.takePhoto(takePhotoOptions);
            // 加时间戳生成唯一文件名,避免重复拍照覆盖
            const targetPath = `${RNFS.ExternalDirectoryPath}/temp_${Date.now()}.jpg`;

            // 直接移动原文件,不要给data.path加前缀/
            await RNFS.moveFile(data.path, targetPath);
            console.log("Image Moved", data.path, '-- to --', targetPath);

            // 触发媒体扫描
            await scanFile(targetPath);
            console.log('照片已保存,可在图库查看');

        }catch(err){    
            console.error(err);
        }
    }

    return(<>
    {device != null&&<>
        <Button title='Take a Photo' onPress={captureHandler}/>
        <View style={{ flex: 1 }}>
            <Camera
                ref={camera}
                style={StyleSheet.absoluteFill}
                device={device}
                photo={true}
                isActive={true}
            />
        </View>
    </>}
    </>)
}

额外注意事项

  • Android 13+需要申请READ_MEDIA_IMAGES权限,WRITE_EXTERNAL_STORAGE在Android 10+已被限制,ExternalDirectoryPath属于应用私有外部存储,无需WRITE权限,但媒体扫描需要对应权限。
  • 如果想让照片直接出现在图库的相机相册,可保存到RNFS.PictureDirectoryPath,但Android 10+需要处理存储访问框架(SAF)。

内容的提问来源于stack exchange,提问作者JayCold

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:55:18