ReactNative 0.66.3上传相机图片到Azure表单识别器报错求正确写法
React Native 对接 Azure Form Recognizer 上传图片修复方案
原有代码核心错误点
- 调用
result.blob()时遗漏await关键字,导致实际传入的是Promise对象而非Blob实例,图片数据无效 - 使用FormData提交时手动设置
Content-Type: image/jpeg属于配置错误,FormData需要对应multipart/form-data类型,且该头不需要手动设置,fetch会自动生成带boundary的合法值 - Azure Form Recognizer 预建收据接口不识别
image_data字段,FormData提交时字段名必须为file - Base64提交时不能带
data:image/jpeg;base64,前缀,必须传入纯base64编码的图片内容,否则会被判定为无效图片
可行实现方案
方案1:直接提交二进制Blob(最优,性能损耗最低)
不需要使用FormData,直接将图片Blob作为请求体即可:
export async function executeScanService(uri, base64data) { try { const url = 'https://<my-endpoint>/formrecognizer/v2.1/prebuilt/receipt/analyze'; // 读取本地图片uri为Blob,补全await const imgResponse = await fetch(uri); const imgBlob = await imgResponse.blob(); const options = { method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': '<替换为你的密钥>', 'Content-Type': 'image/jpeg' // 直接传二进制时该配置正确 }, body: imgBlob }; const response = await fetch(url, options); const respBody = await response.json(); console.log('返回结果', respBody, response.status); return respBody; } catch (error) { console.error('扫描服务报错', error); throw error; } }
方案2:Base64 数据提交
如果需要用已有的base64数据,可先转成Blob再提交:
export async function executeScanService(uri, base64data) { try { const url = 'https://<my-endpoint>/formrecognizer/v2.1/prebuilt/receipt/analyze'; // 先移除base64前缀(如果有的话) const pureBase64 = base64data.replace('data:image/jpeg;base64,', ''); const imgBlob = base64ToBlob(pureBase64, 'image/jpeg'); const options = { method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': '<替换为你的密钥>', 'Content-Type': 'image/jpeg' }, body: imgBlob }; const response = await fetch(url, options); const respBody = await response.json(); console.log('返回结果', respBody, response.status); return respBody; } catch (error) { console.error('扫描服务报错', error); throw error; } } // 辅助函数:base64转Blob function base64ToBlob(base64, contentType = '', sliceSize = 512) { const byteCharacters = atob(base64); const byteArrays = []; for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { const slice = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers = new Array(slice.length); for (let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } byteArrays.push(new Uint8Array(byteNumbers)); } return new Blob(byteArrays, {type: contentType}); }
FormData版本修复(如果必须使用FormData场景)
export async function executeScanService(uri, base64data) { try { const url = 'https://<my-endpoint>/formrecognizer/v2.1/prebuilt/receipt/analyze'; const imgResponse = await fetch(uri); const imgBlob = await imgResponse.blob(); const formData = new FormData(); // 字段名必须为file,不能自定义为其他值 formData.append("file", imgBlob, 'receipt.jpeg'); const options = { method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': '<替换为你的密钥>' // 不要手动设置Content-Type,fetch会自动生成合法值 }, body: formData }; const response = await fetch(url, options); const respBody = await response.json(); console.log('返回结果', respBody, response.status); return respBody; } catch (error) { console.error('扫描服务报错', error); throw error; } }
额外注意事项
- iOS端如果读取本地file://协议的图片失败,需确认
Info.plist中已配置相册/相机访问权限 - 安卓端需确认已申请存储读取权限,targetSDK >=33时需要申请对应图片访问权限
- 确认你的Azure Form Recognizer endpoint和密钥对应区域和服务版本匹配
内容的提问来源于stack exchange,提问作者fullstack_realm
相关产品推荐
相关产品推荐

