如何从React Native WebView向React Native流式传输数据以保存大文件?
React Native WebView 流式传输大文件到本地磁盘方案
针对大文件从WebView传输到React Native并保存到磁盘的需求,你可以采用以下两种高效方案:
方案1:分块传输Base64数据(无需额外Native模块)
将大文件切割成固定大小的块,分批通过postMessage发送,Native端逐块写入文件流,最后完成保存。
WebView端代码
async function splitAndSendFile(file) { const chunkSize = 1024 * 1024; // 按1MB分块,可根据需求调整 let offset = 0; const fileReader = new FileReader(); while (offset < file.size) { const chunk = file.slice(offset, offset + chunkSize); await new Promise(resolve => { fileReader.onload = (e) => { // 剔除Base64前缀,只保留编码内容 const base64Chunk = e.target.result.split(',')[1]; window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'fileChunk', data: base64Chunk, fileName: file.name, chunkOffset: offset, totalSize: file.size })); resolve(); }; fileReader.readAsDataURL(chunk); }); offset += chunkSize; } // 发送传输完成信号 window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'fileComplete', fileName: file.name })); }
React Native端代码
需要依赖react-native-fs库处理文件写入:
import RNFS from 'react-native-fs'; let fileWriteStream = null; let activeFilePath = ''; const handleWebViewMessage = (event) => { const msg = JSON.parse(event.nativeEvent.data); switch (msg.type) { case 'fileChunk': if (!fileWriteStream) { // 初始化文件路径 activeFilePath = `${RNFS.DocumentDirectoryPath}/${msg.fileName}`; // 创建写入流,逐块追加 fileWriteStream = RNFS.appendFile(activeFilePath, msg.data, 'base64'); } else { fileWriteStream = fileWriteStream.then(() => RNFS.appendFile(activeFilePath, msg.data, 'base64') ); } break; case 'fileComplete': fileWriteStream?.then(() => { console.log('文件保存完成:', activeFilePath); fileWriteStream = null; }).catch(err => { console.error('文件保存失败:', err); // 清理未完成文件 RNFS.unlink(activeFilePath); }); break; } }; // 在WebView组件中绑定消息监听 <WebView source={{ uri: '你的网页地址' }} onMessage={handleWebViewMessage} />
方案2:自定义Native通信桥(性能更优)
跳过Base64编码,直接传递二进制数据,减少编码开销,适合超大型文件:
- 在React Native中实现自定义Native模块,暴露
writeFileChunk方法,接收二进制数据和文件信息 - WebView端读取文件的
ArrayBuffer,分块调用Native模块的方法传递原始二进制数据 - Native端直接将二进制数据写入文件流,避免Base64转码的性能损耗
核心思路示例
WebView端:
async function streamFileToNative(file) { const chunkSize = 2 * 1024 * 1024; // 2MB分块 let offset = 0; const fileReader = new FileReader(); while (offset < file.size) { const chunk = file.slice(offset, offset + chunkSize); await new Promise(resolve => { fileReader.onload = (e) => { // 调用自定义Native模块方法传递二进制数据 window.NativeModules.FileWriter.writeChunk( file.name, new Uint8Array(e.target.result), offset, file.size ); resolve(); }; fileReader.readAsArrayBuffer(chunk); }); offset += chunkSize; } window.NativeModules.FileWriter.finishFileWrite(file.name); }
关键注意事项
- 分块大小需平衡:过小会增加通信次数,过大可能导致内存占用过高或
postMessage超时 - 需处理传输中断场景:WebView页面关闭时,Native端要清理未完成的临时文件
- 可添加进度同步:WebView端计算已传输比例,通过
postMessage发送给Native更新UI进度条
内容的提问来源于stack exchange,提问作者user5507535
相关产品推荐
相关产品推荐

