You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native中用axios、XHR、fetch实现JSON数据上传进度展示

问题核心原因

React Native 内置的 XMLHttpRequest 实现对非 multipart/form-data 类型的POST请求,默认不会触发upload progress事件,axios底层调用RN的XHR能力,因此你提供的两种写法都无法正常获取上传进度。

可行解决方法

方案1:改用multipart/form-data格式上传(适配现有API成本最低)

你可以将原本的JSON载荷拆分填充到FormData对象中,base64格式的图片可直接作为普通字段传入,RN会针对FormData类型的请求正确触发上传进度事件。

XMLHttpRequest版本实现

function handleEvent(e) {
    // 先判断长度是否可计算,避免出现NaN
    if (e.lengthComputable) {
        setProgress(Math.round((e.loaded / e.total) * 100))
    }
}

const formData = new FormData();
// 将原有payload的字段逐个填充到FormData
Object.keys(payload).forEach(key => {
    formData.append(key, payload[key]);
});

const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', handleEvent);
xhr.open("POST", url);
xhr.setRequestHeader("Accept", "application/json");
// 无需手动设置Content-Type,RN会自动生成带boundary的正确请求头
xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        console.log(xhr.status);
        console.log(xhr.responseText);
      }
};
xhr.send(formData);

axios版本实现

需要额外添加transformRequest配置,避免axios自动转换FormData格式:

const formData = new FormData();
Object.keys(payload).forEach(key => {
    formData.append(key, payload[key]);
});

var res = await axios.post(BASE_URL + '/crossstorage_addfile', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
        ...headers
      },
      transformRequest: (data) => data,
      onUploadProgress: function (progressEvent) {
        if (progressEvent.lengthComputable) {
            var percentCompleted =  Math.round((progressEvent.loaded * 100) / progressEvent.total)
            console.log(percentCompleted)
        }
      }
});

方案2:必须保留JSON上传格式,使用专用原生上传库

如果业务要求必须发送application/json格式的请求,可以使用react-native-blob-util库,它绕过RN内置XHR的限制,支持所有请求格式的进度监听:

import RNFetchBlob from 'react-native-blob-util';

RNFetchBlob.fetch('POST', url, {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
}, JSON.stringify(payload))
// 每100ms回调一次上传进度
.uploadProgress({ interval : 100 }, (written, total) => {
    const progress = Math.round((written / total) * 100);
    setProgress(progress);
})
.then((res) => {
    const response = res.json();
    // 处理响应逻辑
})
.catch(err => {
    // 处理异常逻辑
})

注意事项

  • 开发环境下如果开启了「Debug Remote JS」,XHR请求会被代理拦截,导致进度事件不触发,测试时请关闭远程调试或打release包验证
  • 服务器端需要正确返回Content-Length响应头,否则会出现lengthComputable为false的情况,无法计算进度百分比

内容的提问来源于stack exchange,提问作者Sanjay Kochrekar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 17:24:08