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

RestTemplate发送MultipartFile列表遇序列化及请求缺失问题求助

问题与解决方案:MultipartFormData请求发送MultipartFile列表异常处理

问题回顾

后端控制器接收MultipartFile列表的接口定义:

@PostMapping(value = "/photos", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(summary = "Accepts photo. Adds photo to queue for sending to Telegram chat")
private void sendPhotos(@RequestPart List<MultipartFile> photos,
                        @RequestParam long cityId,
                        @RequestParam(required = false) String caption) {
   sendToCityChatUseCase.execute(photos, cityId, caption);
}

使用RestTemplate发送请求时,直接添加MultipartFile到MultiValueMap会触发Jackson序列化异常:

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.io.FileDescriptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])

改为添加file.getBytes()后,请求能发送但触发MissingServletRequestPartException,提示缺少"photos"部分。

解决方案

1. 将MultipartFile包装为ByteArrayResource并指定文件名

RestTemplate无法直接序列化MultipartFile,但可以将文件内容包装为ByteArrayResource(保留文件名),这样Spring的MultipartHttpMessageConverter会正确处理为multipart表单的文件部分。同时要将@RequestParam参数也加入MultiValueMap:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);

MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();

// 处理文件列表
for (MultipartFile file : photos) {
    ByteArrayResource resource = new ByteArrayResource(file.getBytes()) {
        @Override
        public String getFilename() {
            return file.getOriginalFilename(); // 必须指定文件名,否则后端无法识别为文件
        }
    };
    formData.add("photos", resource);
}

// 添加RequestParam参数
formData.add("cityId", String.valueOf(cityId));
if (caption != null) {
    formData.add("caption", caption);
}

HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(formData, headers);
ResponseEntity<String> response = restTemplate.postForEntity(chatBotUrl, requestEntity, String.class);

2. 确保RestTemplate配置了MultipartHttpMessageConverter

如果是手动创建的RestTemplate,需要确保其消息转换器列表中包含MultipartHttpMessageConverter。Spring Boot环境下使用RestTemplateBuilder创建的RestTemplate会自动配置该转换器,无需额外操作。若手动创建可参考:

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MultipartHttpMessageConverter());

关键说明

  • 直接传递MultipartFile会触发Jackson序列化,因为RestTemplate默认尝试用Jackson序列化所有非String/Resource类型的对象,而MultipartFile包含不可序列化的FileDescriptor。
  • 使用ByteArrayResource并指定文件名,让MultipartHttpMessageConverter识别为文件part,后端才能通过@RequestPart List<MultipartFile>正确接收。
  • @RequestParam参数需作为普通表单字段加入MultiValueMap,不能放在headers或单独传递。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:05:00