本文详解在裸 React Native 项目中结合 react-native-fs 与 expo-av 实现视频本地缓存与播放的完整方案,重点解决路径格式错误、URI 协议兼容性及缓存策略优化问题,并提供可直接运行的代码示例。 本文详解在裸 react native 项目中结合 `react-native-fs` 与 `expo-av` 实现视频本地缓存与播放的完整方案,重点解决路径格式错误、uri 协议兼容性及缓存策略优化问题,并提供可直接运行的代码示例。在 React Native 中缓存视频并非简单"下载 + 播放",尤其当使用 expo-av(而非 react-native-video)时,文件路径协议、权限配置和 URI 格式要求更为严格。你遇到的"路径不工作"问题,根本原因在于:expo-av 要求传入 source.uri 的必须是 合法的 file:// 协议 URI,而你当前拼接的 {cachePath}/{filename} 仅是原生文件系统路径(如 /Users/.../video.mp4),缺少 file:// 前缀,且未做平台适配处理。? 正确做法是:使用 react-native-fs 下载视频后,通过 RNFS.fileURL()(iOS)或 RNFS.pathToUrl()(Android)生成标准 file URI,再传给 expo-av/Video 组件。以下是经过验证的完整实现:import React, { useState, useEffect } from 'react';import { View } from 'react-native';import * as RNFS from 'react-native-fs';import { Video } from 'expo-av';const App = ({ videoUrl }: { videoUrl: string }) => { const cachedUri, setCachedUri = useState<string | null>(null); useEffect(() => { downloadAndCacheVideo(); }, \[\]); const downloadAndCacheVideo = async () => { try { const filename = videoUrl.substring(videoUrl.lastIndexOf('/') + 1); const cachePath = RNFS.DocumentDirectoryPath; const localPath = `{cachePath}/{filename}`; // ? 检查文件是否存在(推荐用 stat 替代 exists,更可靠) const stat = await RNFS.stat(localPath).catch(() => null); if (stat && stat.isFile()) { console.log('? Video already cached:', localPath); // ? 生成跨平台 file:// URI const fileUri = Platform.OS === 'ios' ? `file://{localPath}\` : RNFS.pathToUrl(localPath); // Android requires pathToUrl setCachedUri(fileUri); return; } // ? 下载视频(注意:fetch + blob 在某些 RN 版本存在兼容性问题,推荐用 RNFS.downloadFile) console.log('?? Downloading video...'); const downloadRes = await RNFS.downloadFile({ fromUrl: videoUrl, toFile: localPath, progress: (data) =\> { console.log(\`Download progress: {Math.round(data.bytesWritten / data.contentLength * 100)}%`); } }).promise; if (downloadRes.statusCode === 200) { const fileUri = Platform.OS === 'ios' ? `file://{localPath}\` : RNFS.pathToUrl(localPath); setCachedUri(fileUri); console.log('? Cached video URI:', fileUri); } else { throw new Error(\`Download failed: {downloadRes.statusCode}`); } } catch (err) { console.error('? Cache failed:', err); } }; return ( <View style={{ flex: 1 }}> {cachedUri ? ( <Video source={{ uri: cachedUri }} resizeMode="cover" shouldPlay isMuted={false} useNativeControls style={{ width: '100%', height: 300 }} /> ) : ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Loading cached video...</Text> </View> )} </View> );};export default App;? 关键注意事项与最佳实践: 稿定AI 拥有线稿上色优化、图片重绘、人物姿势检测、涂鸦完善等功能
相关推荐
东北赵四5 分钟前
关于Java泛型的知识点及其相关面试题姓蔡小朋友6 分钟前
Java线程并发海带紫菜菠萝汤11 分钟前
免费在线翻译器横评:2026年6款PDF翻译工具对比行业研究员41 分钟前
腾讯云数据库:团队知识统一检索实践朱容zr3331331 小时前
什么是覆盖索引?它的优点是什么?一十九的酒1 小时前
Oracle Data Guard 备库归档日志满导致同步中断的解决实战changjiahong1 小时前
lvs总结【心态好不摆烂】1 小时前
MySQL——复合查询编程阿峰1 小时前
Python 环境配置(二)安装jupyter、matplotlib、numpy库AC赳赳老秦1 小时前
CSDN 技术社区数据采集:OpenClaw 抓取公开技术热帖,生成领域技术热点周报