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

React Native使用Expo Image Picker+Axios上传图片至服务器失败求助

Expo ImagePicker 图片上传失败问题排查与修复

我使用expo-image-picker作为UI组件实现图片上传功能,但图片始终无法上传到后端,尝试多种方法均未解决。以下是我的原代码实现:

1. 图片状态设置逻辑

const showImagePicker = async () => {
  Promise.all([ImagePicker.requestMediaLibraryPermissionsAsync(), ImagePicker.requestCameraPermissionsAsync()]).then(result => {
    result.forEach(permission => {
      return !permission.granted;
    });
  });

  const result: ImagePicker.ImageInfo = (await ImagePicker.launchImageLibraryAsync({
    base64: true,
  })) as ImagePicker.ImageInfo;

  const uriParts = result.uri.split('.');
  const fileType = uriParts[uriParts.length - 1];

  if (!result.cancelled) {
    setPickedImagePath({
      uri: Platform.OS === 'android' ? result.uri : result.uri.replace('file://', ''),
      name: `photo.${fileType}`,
      type: `application/${fileType}`,
    });
  }
};

2. FormData追加数据逻辑

const createRequestCall = async () => {
  const formData = new FormData();
  formData.append('file', pickedImage.uri);
  formData.append('data2', 'test');
  formData.append('data3', '123');
  formData.append('data4', 'test');

  dispatch(uploadPhoto(formData));
};

3. 请求分发逻辑

export const uploadPhoto=
      (photoRequest: FormData) =>
      async (dispatch: Dispatch<Action>): Promise<void> => {
        dispatch({ type: ActionTypes.API_LOADING, payload: apiIsLoading });
        const response = await Apis.requestPhoto(fileRequest);
        dispatch({ type: ActionTypes.API_LOADING, payload: apiIsNotLoading });
      };

4. 后端请求逻辑

async requestPhoto(data: FormData): Promise<IDetails> {
    const response = await http.post<IDetails, AxiosResponse<ITripDetailsResponse>>(`${baseURL}/upload/image`, data, {
      headers: { 'Content-Type': 'multipart/form-data' },
      transformRequest(formData, headers) {
        return data;
      },
    });
    return response.data;
  },

问题分析与修复方案

1. 权限请求逻辑错误

原代码未等待权限请求结果,也未正确判断权限是否授予,forEach内的return无法终止后续代码,会导致无权限时仍执行选图逻辑。同时图片MIME类型设置错误,应该用image/xxx而非application/xxx。

修正后代码:

const showImagePicker = async () => {
  // 等待权限请求完成
  const [mediaPerm, cameraPerm] = await Promise.all([
    ImagePicker.requestMediaLibraryPermissionsAsync(),
    ImagePicker.requestCameraPermissionsAsync()
  ]);

  // 权限未授予则终止流程
  if (!mediaPerm.granted || !cameraPerm.granted) {
    alert('需要授予图片访问权限才能上传');
    return;
  }

  const result: ImagePicker.ImageInfo = (await ImagePicker.launchImageLibraryAsync({
    base64: true,
  })) as ImagePicker.ImageInfo;

  if (result.cancelled) return;

  // 正确识别图片MIME类型
  const fileType = result.uri.split('.').pop();
  let mimeType = 'image/jpeg';
  if (fileType === 'png') mimeType = 'image/png';
  else if (fileType === 'gif') mimeType = 'image/gif';

  setPickedImagePath({
    uri: Platform.OS === 'android' ? result.uri : result.uri.replace('file://', ''),
    name: `photo.${fileType}`,
    type: mimeType,
  });
};

2. FormData追加文件错误

原代码仅传递图片uri字符串,FormData需要接收包含uri、name、type的完整对象才能识别为文件。

修正后代码:

const createRequestCall = async () => {
  if (!pickedImage) return; // 先判断是否选中图片

  const formData = new FormData();
  // 传入完整的文件对象
  formData.append('file', pickedImage as any);
  formData.append('data2', 'test');
  formData.append('data3', '123');
  formData.append('data4', 'test');

  dispatch(uploadPhoto(formData));
};

3. 请求分发逻辑变量名错误

原代码入参为photoRequest,但调用接口时用了未定义的fileRequest,导致参数传递错误。

修正后代码:

export const uploadPhoto = (photoRequest: FormData) => async (dispatch: Dispatch<Action>): Promise<void> => {
  dispatch({ type: ActionTypes.API_LOADING, payload: apiIsLoading });
  // 使用正确的入参变量名
  const response = await Apis.requestPhoto(photoRequest);
  dispatch({ type: ActionTypes.API_LOADING, payload: apiIsNotLoading });
};

4. 后端请求配置错误

手动设置Content-Type: multipart/form-data会丢失自动生成的boundary,Axios会自动处理FormData的Content-Type;多余的transformRequest会干扰默认的表单数据转换。

修正后代码:

async requestPhoto(data: FormData): Promise<IDetails> {
  const response = await http.post<IDetails, AxiosResponse<ITripDetailsResponse>>(
    `${baseURL}/upload/image`,
    data
  );
  return response.data;
},

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:30:29