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

使用Spring WebClient上传Multipart文件调用REST API报错求助

问题:Spring WebClient传输文件时序列化报错

我有一个使用Spring WebClient调用REST API的场景,需在请求中传递图片或PDF文件。我通过内部方法downloadFile()获取到File类型的文件,当前采用如下方式传输文件:

File file = downloadFile(key);
InputStream stream = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getName(), "multipart/form-data", stream);
JsonNode response = Objects.requireNonNull(webClient.post()
                .uri("/api/{groupId}/images", uriBuilder -> uriBuilder
                    .queryParam("referenceId", referenceId)
                    .build(Map.of("groupId", 1000)))
                .header(HttpHeaders.AUTHORIZATION, "Bearer " + auth2Service.getAccessToken())
                .bodyValue(multipartFile)
                .retrieve()
                .bodyToMono(JsonNode.class)
                .block());

但出现如下错误:

"Type definition error: [simple type, class java.io.ByteArrayInputStream]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.mock.web.MockMultipartFile["inputStream"])"

请问我当前的文件发送方式是否正确?若正确,该错误的原因是什么?


解答
  • 当前的文件发送方式不正确,错误原因及修正方案如下:
  1. 错误原因:
    使用bodyValue()传递MockMultipartFile时,WebClient会默认用Jackson序列化该对象,但MockMultipartFile内部的ByteArrayInputStream没有对应的Jackson序列化器,导致序列化失败抛出上述错误。且bodyValue()并不适合构建multipart/form-data类型的请求。

  2. 正确的文件传输方式:
    发送multipart请求需使用BodyInserters.fromMultipartData()构建请求体,示例代码如下:

File file = downloadFile(key);
// 直接用FileSystemResource包装File,无需转成MockMultipartFile
MultiValueMap<String, Object> multipartData = new LinkedMultiValueMap<>();
multipartData.add("file", new FileSystemResource(file));

JsonNode response = Objects.requireNonNull(webClient.post()
                .uri(uriBuilder -> uriBuilder.path("/api/{groupId}/images")
                    .queryParam("referenceId", referenceId)
                    .build(1000))
                .header(HttpHeaders.AUTHORIZATION, "Bearer " + auth2Service.getAccessToken())
                .body(BodyInserters.fromMultipartData(multipartData))
                .retrieve()
                .bodyToMono(JsonNode.class)
                .block());

若一定要使用MultipartFile,可按以下方式处理:

// 指定文件实际的Content-Type,比如图片用image/jpeg,PDF用application/pdf
MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getName(), "application/octet-stream", new FileInputStream(file));
MultiValueMap<String, Object> multipartData = new LinkedMultiValueMap<>();
multipartData.add("file", multipartFile);

// 后续WebClient调用同样使用BodyInserters.fromMultipartData(multipartData)

额外注意:

  • MockMultipartFile主要用于测试场景,生产环境优先用FileSystemResource包装File,更简洁高效;
  • 不要将multipart/form-data作为单个文件的Content-Type,应使用文件对应的实际类型,或通用的application/octet-stream。

内容的提问来源于stack exchange,提问作者Chandra Shekar Bairi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 13:45:30