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

React Native Expo + Axios 图片上传间歇性网络错误求助

Expo React Native 图片上传间歇性Axios网络错误排查方案

问题概述

基于Expo ^50.0.7开发的React Native项目中,用户头像上传函数存在间歇性失败问题:每4-5次上传会触发一次"Axios Network Error",但相同请求在Postman中每次都能成功执行,问题锁定在前端。

已尝试的无效方案

  • 将请求目标从localhost改为IP地址,规避本地网络解析问题
  • 修改请求头Content-Type为小写content-type
  • 调整FormData的参数配置
  • 升级/降级Axios版本
  • 后端配置CORS相关规则

核心代码片段

上传请求函数

const handleUpload = async (formData) => {
  try {
    const token = await getFromAsyncStorage(Keys.AUTH_TOKEN);
    const response = await axios.post(
      "http://<my-ip-address>/auth/profile-image-upload",
      formData,
      {
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "multipart/form-data;",
        },
      }
    );
    return response.data;
  } catch (error) {
    console.error(error);
    throw error;
  }
};

FormData生成逻辑

// 请求相机权限
const hasPermission = await requestCameraPermissionsAsync();
if (!hasPermission) return;

// 调用ImagePicker打开相机
const result = await ImagePicker.launchCameraAsync({
    cameraType: ImagePicker.CameraType.front,
    allowsEditing: true,
    aspect: [1, 1],
    quality: 0.2,
});

if (result.canceled) return;

setIsLoading(true);

const file = result.assets[0];
const formData = new FormData();
formData.append("avatar", {
    uri: file.uri,
    type: "image/jpeg",
    name: "profile",
} as any);

const data = await handleUpload(formData);

排查与解决思路

  1. 移除手动设置的Content-Type
    Axios发送FormData时会自动生成包含boundary分隔符的正确Content-Type,手动设置"multipart/form-data;"会丢失关键的boundary信息,导致后端无法解析请求,这很可能是间歇性失败的核心原因。修改后的上传函数:

    const handleUpload = async (formData) => {
      try {
        const token = await getFromAsyncStorage(Keys.AUTH_TOKEN);
        const response = await axios.post(
          "http://<my-ip-address>/auth/profile-image-upload",
          formData,
          {
            headers: {
              Authorization: `Bearer ${token}`,
              // 移除手动设置的Content-Type
            },
          }
        );
        return response.data;
      } catch (error) {
        console.error(error);
        throw error;
      }
    };
    
  2. 统一处理跨平台URI格式
    Expo ImagePicker在iOS返回file://格式URI,Android返回content://格式,部分情况下会导致文件读取异常。可以统一转换为标准文件路径:

    import { Platform } from 'react-native';
    import * as FileSystem from 'expo-file-system';
    
    // 处理URI格式兼容
    let uri = file.uri;
    if (Platform.OS === 'android' && uri.startsWith('content://')) {
      const fileInfo = await FileSystem.getInfoAsync(uri);
      uri = fileInfo.uri;
    }
    
    formData.append("avatar", {
        uri: uri,
        type: file.mimeType || "image/jpeg",
        name: file.fileName || `profile_${Date.now()}.jpg`,
    } as any);
    

    优先使用ImagePicker返回的mimeType和fileName,避免硬编码带来的类型不匹配问题。

  3. 添加超时与重试机制
    间歇性错误可能和网络波动有关,给请求添加超时限制并配置自动重试:

    import axiosRetry from 'axios-retry';
    
    // 全局配置Axios重试规则
    axiosRetry(axios, {
      retries: 2,
      retryDelay: (count) => count * 1000,
      retryCondition: (error) => {
        return axiosRetry.isNetworkError(error) || (error.response?.status >= 500);
      },
    });
    
    // 上传函数中添加超时配置
    const response = await axios.post(
      "http://<my-ip-address>/auth/profile-image-upload",
      formData,
      {
        headers: { Authorization: `Bearer ${token}` },
        timeout: 30000, // 30秒超时
      }
    );
    
  4. 细化错误日志
    在catch块中打印更详细的错误信息,帮助定位问题根源:

    catch (error) {
      console.error('上传错误详情:', {
        message: error.message,
        code: error.code,
        responseData: error.response?.data,
        requestDetails: error.request,
      });
      throw error;
    }
    
  5. 前置网络状态检查
    在上传前确认设备网络连接状态,避免无网情况下的无效请求:

    import NetInfo from '@react-native-community/netinfo';
    
    const networkState = await NetInfo.fetch();
    if (!networkState.isConnected) {
      throw new Error('当前网络不可用,请检查网络连接');
    }
    

内容的提问来源于stack exchange,提问作者Michael ilkanayev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:23:23