React Native中如何实现与Node.js一致的POST二进制Blob发送功能?
解决React Native中FormData上传文件服务器无法识别负载的问题
原始Node.js函数
fn: async () => { var start = Date.now() var ab = new ArrayBuffer(tuneFile.length); //bytes is the array with the integer var ia = new Uint8Array(ab); for (var i = 0; i < tuneFile.length; i++) { ia[i] = tuneFile[i]; } var blob = new Blob([ia], { type: "application/octet-stream" }); var form = new FormData(); form.append("file", blob, "tune1.bin") const requestOptions = { method: 'POST', body: form, }; const response = await fetch('http://192.168.4.1/upload', requestOptions); const data = await response.text(); console.log(data) var end = Date.now(); console.log(end - start) return true }
存在问题的React Native版本函数
fn: async () => { var start = Date.now() var ab = new ArrayBuffer(tuneFile.length); //bytes is the array with the integer var ia = new Uint8Array(ab); for (var i = 0; i < tuneFile.length; i++) { ia[i] = tuneFile[i]; } var blob = new Blob([ia], {type: 'multipart/form-data'}); var form = new FormData(); form.append("file", blob, "tune1.bin") const config = { headers: { 'Content-Type': blob.type, } }; axios.post('http://192.168.4.1/upload', form, config) .then(res => { console.log(res.request.status) return true; }) .catch(err => console.log(err)) //var end = Date.now(); //return true }
问题分析
- Blob类型错误:原函数中Blob的MIME类型是
application/octet-stream(二进制流),但RN版本错误设置为multipart/form-data,导致文件类型标识错误,服务器无法正确解析内容。 - 手动设置Content-Type破坏表单边界:axios发送FormData时会自动生成带正确分隔边界的
multipart/form-data请求头,手动设置该字段会覆盖自动生成的内容,导致服务器无法识别表单字段边界,进而读取不到文件负载。 - React Native对Blob的兼容性局限:RN的Blob实现存在兼容性问题,直接用Uint8Array构建Blob可能出现解析异常。
- 异步逻辑不统一:原函数用
async/await处理异步请求,RN版本混用then/catch,不利于错误处理和逻辑一致性。
修改后的React Native函数
fn: async () => { const start = Date.now() // 用ia.set替代手动循环,更高效且兼容RN const ia = new Uint8Array(tuneFile.length); ia.set(tuneFile); // 恢复原函数的Blob类型:application/octet-stream const blob = new Blob([ia], { type: "application/octet-stream" }); const form = new FormData(); form.append("file", blob, "tune1.bin"); try { // 移除手动设置的Content-Type,让axios自动处理表单头 const res = await axios.post('http://192.168.4.1/upload', form); console.log(res.request.status); console.log(res.data); const end = Date.now(); console.log(end - start); return true; } catch (err) { console.log(err); return false; } }
额外兼容方案(绕过RN Blob问题)
如果上述修改仍有问题,可以直接跳过Blob,用Base64编码传递二进制数据:
fn: async () => { const start = Date.now() const form = new FormData(); // 将二进制数据转为Base64,直接通过FormData传递 form.append("file", { uri: `data:application/octet-stream;base64,${Buffer.from(tuneFile).toString('base64')}`, name: "tune1.bin", type: "application/octet-stream" }); try { const res = await axios.post('http://192.168.4.1/upload', form); console.log(res.request.status); console.log(res.data); const end = Date.now(); console.log(end - start); return true; } catch (err) { console.log(err); return false; } }
修改说明
- 恢复Blob的MIME类型与原函数一致,确保文件类型标识正确。
- 移除手动设置的
Content-Type,让axios自动生成符合规范的表单请求头。 - 用
ia.set(tuneFile)替代手动循环,简化代码同时提升兼容性。 - 统一使用
async/await处理异步请求,便于错误捕获和流程控制。 - 额外方案通过Base64编码绕过RN的Blob兼容性问题,确保二进制数据正常传递。
内容的提问来源于stack exchange,提问作者hamza765
相关产品推荐
相关产品推荐

