React Native中xhr.upload.onprogress上传进度显示不准确问题
React Native Android端上传进度不准确问题排查
在React Native Android应用中,使用XHR或Axios上传图片/视频时,上传功能正常,但进度回调返回的数据严重不准确。例如上传70MB左右的大文件时,进度会在几秒内从0%跳到69%、98%再到100%,但实际上传耗时需要1-2分钟。
原XHR实现代码
const formData = new FormData(); formData.append("FileInput", { uri: uri, type: "video/" + ext, name: fileName, }); const xhr = new XMLHttpRequest(); xhr.open("POST", url); xhr.onload = () => { const response = JSON.parse(xhr.response); resolve(true); }; xhr.onerror = (e) => { console.log(e, "upload failed"); }; xhr.ontimeout = (e) => { console.log(e, "upload timeout"); }; xhr.send(formData); if (xhr.upload) { xhr.upload.onprogress = ({ total, loaded }) => { uploadProgress = Math.round((loaded / total) * 100); console.log(uploadProgress, total, loaded); }; }
更新:Axios实现同样存在问题
换用Axios上传后,遇到完全一致的情况:onUploadProgress很快显示100%,但实际上传耗时远久于此。
const config = { onUploadProgress: (progressEvent) => { uploadProgress = Math.round((progressEvent.loaded / progressEvent.total) * 100); console.log(uploadProgress); }, headers: { "Content-Type": "multipart/form-data" }, }; const upload = await axios.post(url, formData, config);
可能的原因及解决方向
- React Native FormData的本地预读取机制:RN在发送FormData前会先将本地文件读取到内存,这个阶段的进度会被计入
loaded,但这只是本地读取进度,并非真实的网络上传进度。本地读取完成后,网络上传阶段没有进度更新,直到上传完成直接跳至100%。 - Android底层网络的缓冲机制:RN底层依赖的Android HttpURLConnection(或OkHttp)会先将请求体缓存到本地,再一次性发送到服务器,导致进度回调仅在缓存完成时触发,无法反映真实的网络上传过程。
- 文件URI类型问题:如果使用的是
content://类型的URI,RN可能无法正确获取文件的真实大小和跟踪上传进度,导致total值不准确,进而引发进度计算偏差。
可行的解决办法
- 使用原生上传库:比如
react-native-fs这类库直接调用原生平台的上传API,能精准跟踪真实的网络上传进度。 - 实现分块上传:将大文件拆分为多个小块逐个上传,自行计算总进度,这种方式能得到真实的上传进度,但需要后端配合支持分块上传逻辑。
- 调整Android网络配置:针对OkHttpClient(RN 0.60+默认使用),可以自定义配置关闭请求体缓冲,让进度回调能实时反映网络上传状态。
内容的提问来源于stack exchange,提问作者Simon Harvey
相关产品推荐
相关产品推荐

