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

React Native fetch上传Blob/File至服务器失败问题排查

问题定位

你遇到的上传失败、报Network request failed、服务器收不到附件的问题,核心是两个写法错误,和权限、第三方服务SDK没有关系:

  • 错误1:手动给请求写死了Content-Type: multipart/form-data请求头。React Native/Expo环境下发送FormData请求时,必须让框架自动生成这个请求头——自动生成的头会附带随机生成的boundary分隔符,用来标记表单里不同字段的边界。你手动写死头之后没有这个分隔符,服务器完全无法解析表单结构,自然识别不到附件,会把请求判定为空请求。
  • 错误2:用fetch(本地uri).blob()的方式转文件格式。Expo内置的fetch对本地file://协议资源的blob转换存在已知兼容问题,转出来的文件大概率是空值或者损坏格式,你注释掉的直接传uri配置对象的写法才是RN生态的标准实现,TS的类型报错是因为官方类型定义没有覆盖RN原生层支持的传参格式,直接忽略即可,不是写法错误。
修复方案

按以下步骤调整代码即可:

  • 第一步:删除请求头中手动配置的"Content-Type": "multipart/form-data"字段,Accept字段可以保留,不要手动干预表单请求的Content-Type生成。
  • 第二步:移除你写的fetchImageFromUri转blob的逻辑,换回直接传递文件元信息对象的写法,注意不要裁剪ImagePicker返回的uri前缀,iOS返回的file://开头路径要完整传入。
  • 第三步:如果使用Expo SDK 48及以上版本,只需要在app.json中配置iOS的相册权限描述即可,不需要加任何针对Android 5.0以下版本的过时存储权限配置,那些5年以上的老教程内容完全不适配当前版本。

修复后的核心上传代码如下:

const upload = async () => {
  setMessage("");
  setErrMessage("");

  if (pathToImage != null) {
    const formData = new FormData();
    formData.append("action", "Image Upload");
    
    // 直接传递文件配置对象,忽略TS类型报错
    const uriParts = pathToImage.split(".");
    const fileType = uriParts[uriParts.length - 1];
    formData.append("image", {
      uri: pathToImage,
      name: `photo.${fileType}`,
      type: `image/${fileType}`,
      // @ts-ignore RN原生层支持该传参格式,TS类型定义未覆盖
    } as any);

    const options: RequestInit = {
      method: "POST",
      body: formData,
      headers: {
        Accept: "application/json",
        // 不要手动设置multipart/form-data头,让框架自动生成
      },
    };

    try {
      const res = await fetch(URL, options);
      if (!res.ok) {
        throw new Error("服务端返回异常状态");
      }
      const body = (await res.json()) as any;
      if (body.code > 200) {
        setErrMessage(body.msg);
      } else {
        setMessage(body.msg);
      }
    } catch (err: any) {
      setErrMessage("上传失败,请重试");
      console.log("upload catch error:", err.message);
    }
  }
};
补充排查点

如果改完代码仍有问题,按以下顺序排查:

  • 检查请求地址是否为HTTP明文地址,Android 9以上版本默认禁止明文HTTP请求,要么换成HTTPS地址,要么在配置中开启明文流量允许。
  • 真机调试时不要用localhost作为服务端地址,localhost指向的是手机设备本身,要换成你开发机所在局域网的实际IP。
  • 不要引入第三方form-data的polyfill包,Expo/RN内置的FormData实现已经足够,额外引入polyfill会导致boundary生成逻辑冲突,触发同样的报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 11:06:33