React Native应用上传图片到Firebase后Google Vision API失效求解
解决方案
问题定位
你的问题核心是imageUploadToFirebase函数中重写了**全局window.fetch**方法:
- RNFetchBlob的自定义Fetch polyfill默认仅对配置的
binaryContentTypes(图片/视频/音频等)做特殊处理,Google Vision API的JSON请求不属于该列表,会被错误序列化导致请求失效 - 该全局替换是持久化的,只要执行过一次上传函数,后续所有网络请求都会使用被修改的fetch,这也能解释你补充的「先调用Vision再上传,第二次调用Vision就失效」的现象
修复方案
方案1:删除全局polyfill替换逻辑,局部使用RNFetchBlob能力(最推荐)
不要修改全局的Blob、XMLHttpRequest、fetch,直接用RNFetchBlob的自带方法上传文件,避免污染全局环境。修改后的imageUploadToFirebase代码如下:
const imageUploadToFirebase = async (imageData) => { let newItemKey = Firebase.database().ref().child('usersummary').push().key; let _name = newItemKey + 'img.jpg'; setIsLoading(true); const path = Platform.OS === "ios" ? imageData.uri.replace("file://", "") : imageData.uri; try { // 直接用RNFetchBlob上传,不需要替换全局API const res = await RNFetchBlob.fs.readFile(path, 'base64'); const blob = await RNFetchBlob.polyfill.Blob.build(res, { type: 'image/jpg;BASE64' }); await Firebase.storage() .ref("scannedItems/" + _name) .put(blob); blob.close(); const uploadedFile = await Firebase.storage() .ref("scannedItems/" + _name) .getDownloadURL(); setFirebaseImageURL(uploadedFile); // 此处调用Vision API即可正常运行 callGoogleVisionApi(imageData.base64); } catch (error) { console.log('上传错误:', error); } }
方案2:上传完成后还原全局fetch(临时兼容方案)
如果暂时不想改上传逻辑,可以在替换全局fetch前先保存原始的fetch实例,上传完成后还原:
const imageUploadToFirebase = (imageData) => { // 先保存原始的全局fetch const originalFetch = window.fetch; const Blob = RNFetchBlob.polyfill.Blob; const fs = RNFetchBlob.fs; window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest; window.Blob = Blob; const Fetch = RNFetchBlob.polyfill.Fetch window.fetch = new Fetch({ auto: true, binaryContentTypes: [ 'image/', 'video/', 'audio/', 'foo/', ] }).build() let uploadBlob = null; var path = Platform.OS === "ios" ? imageData.uri.replace("file://", "") : imageData.uri var newItemKey = Firebase.database().ref().child('usersummary').push().key; var _name = newItemKey + 'img.jpg'; setIsLoading(true) fs.readFile(path, "base64") .then(data => { let mime = "image/jpg"; return Blob.build(data, { type: `${mime};BASE64` }); }) .then(blob => { uploadBlob = blob; return Firebase.storage() .ref("scannedItems/" + _name) .put(blob) }) .then(() => { uploadBlob.close(); return Firebase.storage() .ref("scannedItems/" + _name) .getDownloadURL(); }) .then(async uploadedFile => { setFirebaseImageURL(uploadedFile) // 还原全局fetch后再调用Vision API window.fetch = originalFetch; callGoogleVisionApi(imageData.base64) }) .catch(error => { // 出错也要还原fetch,避免后续请求异常 window.fetch = originalFetch; console.log({ error }); }); }
额外注意点
- 检查
callGoogleVisionApi的拼写一致性,你的函数定义里误写为callGoogleVIsionApi(第二个i大写),避免调用时报错 - 不要在
callGoogleVisionApi里直接修改全局的newArr变量,建议通过返回值把结果传递出去,避免副作用
内容的提问来源于stack exchange,提问作者SatelBill
相关产品推荐
相关产品推荐

