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
相关产品推荐
相关产品推荐

