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

React Native Expo无法发送带图片的Multipart/Form POST请求(Spring后端)

React Native Expo + Spring 后端:multipart/form-data 请求丢失advertisement字段问题

问题描述

React Native Expo移动端应用搭配Spring后端,发送包含图片的multipart/form-data类型POST请求时,后端抛出Required part 'advertisement' is not present错误。基于React的Web应用使用几乎相同的代码可正常运行,但移动端处理multipart请求时异常。

前端核心代码(handlePost函数)

const handlePost = async () => {
    const formDataToSend = new FormData();

    const advertisementBlob = new Blob([JSON.stringify(formData)], {
      type: "application/json",
    });
    formDataToSend.append("advertisement", advertisementBlob);
    imageUris.forEach((img) => {
      const media = {
        uri: img,
        type: "image/jpeg",
        name: "profile.jpg",
      };
      // const file = new File([blob]);
      formDataToSend.append("files", media);
    });
    try {
      console.log(JSON.stringify(formDataToSend));
      const result = await postAdd(formDataToSend);
      console.log(result);
    } catch (error) {
      console.log(error);
    }
  };

Spring后端报错日志

2024-07-14 02:10:54 2024-07-13T21:10:54.069Z  WARN 1 --- [nio-3001-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required part 'advertisement' is not present.]

后端核心代码

@PostMapping(value = "/create", consumes = "multipart/form-data")
public ResponseEntity<?> saveAdvertisement(@RequestPart("advertisement") AdvertisementDTO aDto,
        @RequestPart("files") List<MultipartFile> files) {
    return facade.saveAdvertisement(aDto, files);
}

public ResponseEntity<?> saveAdvertisement(AdvertisementDTO aDto,
        List<MultipartFile> files) {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    User currentUser = (User) authentication.getPrincipal();
    Advertisement advertisement = Advertisement.builder()
            .title(aDto.getTitle())
            .description(aDto.getDescription())
            .category(catService.findById(aDto.getCategory().getCategory_id()))
            .user(currentUser)
            .price(aDto.getPrice())
            .date(LocalDateTime.now())
            .views(0L)
            .build();
    String result = iService.validateAndSaveImages(files);
    if (result != null)
        return ResponseEntity.badRequest().body(result);
    advertisement.setImages(files);

    try {
        service.save(advertisement);
        return ResponseEntity.ok().body("{\"status\":\"SUCCESS\"}");

    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("Advertisement creation failed: " + e.getMessage());
    }
}

请求配置

query: (newAdd) => {
    return {
        url: "/api/secured/create",
        method: "POST",
        body: newAdd,
    };
},
invalidatesTags: [{ type: "Advertisements", id: "LIST" }],

请求Payload JSON

{
"_parts":
[
  ["advertisement",{"_data":{"blobId":"923737fc-8e5d-43d9-adec-af0fb0ff933d","offset":0,"size":80,"type":"application/json","__collector":{}}}],
  ["files",{"uri":"file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252FCoreComponent-b964cf2e-b055-4d78-9e16-7ff1dbf5bec4/ImagePicker/83bd2379-6703-4a54-8764-e5427389de54.png","type":"image/jpeg","name":"profile.jpg"}]
]
}

解决方案

1. 修正advertisement字段的FormData添加方式

React Native的FormData对Blob的处理逻辑和Web不同,直接传入Blob会导致后端无法正确解析该字段。改为直接传入JSON字符串,并指定文件名和类型:

// 替换原Blob相关代码
formDataToSend.append("advertisement", JSON.stringify(formData), {
  filename: "advertisement.json",
  type: "application/json"
});

2. 禁止手动设置Content-Type请求头

确保请求工具(如fetch、react-query)没有手动设置Content-Type: multipart/form-data,让React Native自动生成包含boundary的请求头。手动设置会丢失boundary信息,导致后端无法正确拆分multipart数据。

3. 验证图片URI格式

如果使用Expo ImagePicker获取图片,确保返回的uri是file://开头的本地路径。若遇到Android路径问题,可使用expo-file-system验证文件存在:

import * as FileSystem from 'expo-file-system';

// 示例:验证文件存在
const verifyFile = async (uri) => {
  const info = await FileSystem.getInfoAsync(uri);
  return info.exists;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:22:22