Firebase存储与Firestore音频上传遇Range Error及网络请求错误求助
问题诊断与修复方案
核心问题分析
你遇到的Range Error、网络请求错误以及音频仅上传少量字节的问题,大概率是DocumentPicker获取的音频文件URI无法被fetch完整读取导致的:
- 当
copyToCacheDirectory: false时,直接通过原URI fetch可能因系统权限限制,只能读取文件的部分内容,生成不完整的Blob。 - 音频文件体积通常远大于图片,这种不完整Blob会触发Firebase上传的Range Error,同时导致上传内容缺失。
修复步骤
1. 修改DocumentPicker配置,启用缓存目录复制
将copyToCacheDirectory设为true,确保获取到的是可完整读取的本地缓存文件URI:
async function pickAudio() { try { const result = await DocumentPicker.getDocumentAsync({ type: "audio/*", copyToCacheDirectory: true, // 改为true,确保文件可完整读取 }); if (!result.canceled) { setAudioFile(result.assets[0].uri); setAudioFilename(result.assets[0].name); const response = await fetch(result.assets[0].uri); const blob = await response.blob(); // 新增:验证Blob大小,确认文件完整 console.log("音频Blob大小:", blob.size); setAudioBlob(blob); } } catch (error) { console.error("选择音频出错:", error); } }
2. 优化音频Blob的生成方式(备选方案)
如果启用缓存后仍有问题,可通过react-native-fs直接读取文件内容生成Blob,避免fetch的权限问题:
// 先安装依赖:npm install react-native-fs import RNFS from 'react-native-fs'; async function pickAudio() { try { const result = await DocumentPicker.getDocumentAsync({ type: "audio/*", copyToCacheDirectory: true, }); if (!result.canceled) { setAudioFile(result.assets[0].uri); setAudioFilename(result.assets[0].name); // 用RNFS读取文件内容,再转为Blob const fileContent = await RNFS.readFile(result.assets[0].uri, 'base64'); const blob = await fetch(`data:audio/${result.assets[0].type};base64,${fileContent}`).then(res => res.blob()); console.log("音频Blob大小:", blob.size); setAudioBlob(blob); } } catch (error) { console.error("选择音频出错:", error); } }
3. 上传时添加错误处理与进度监控
在upload函数中添加上传进度监听,便于排查网络请求错误:
async function upload(audioBlob, imageBlob) { const audioStorageRef = ref(storage, "audioSermon/" + new Date().getTime()); const audioUploadTask = uploadBytesResumable(audioStorageRef, audioBlob); // 监听音频上传进度与错误 audioUploadTask.on('state_changed', (snapshot) => { const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log(`音频上传进度:${progress}%`); }, (error) => { console.error("音频上传错误:", error); // 根据错误类型处理:比如重新上传、提示用户 } ); const imageStorageRef = ref(storage, "albumArt/" + new Date().getTime()); const imageUploadTask = uploadBytesResumable(imageStorageRef, imageBlob); try { const [audioSnapshot, imageSnapshot] = await Promise.all([ audioUploadTask, imageUploadTask, ]); const audioDownloadUrl = await getDownloadURL(audioSnapshot.ref); const imageDownloadUrl = await getDownloadURL(imageSnapshot.ref); await saveRecord( audioDownloadUrl, imageDownloadUrl, title, preacher, series, new Date().getTime() ); setAudioFile(""); setImageFile(""); console.log("上传完成"); navigation.navigate("admin/adManage/audioSermon"); } catch (error) { console.error("获取下载链接或保存记录出错:", error); } }
验证要点
- 选择音频后,查看控制台打印的Blob大小,确认与原文件大小一致。
- 上传时监控进度,确保进度能达到100%,没有中途中断。
内容的提问来源于stack exchange,提问作者lyon98.dbios
相关产品推荐
相关产品推荐

