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

Spring Boot 2.7.5 WebClient Multipart文件上传报400错误,求解决方案

问题

基于Spring Boot 2.7.5的WebClient应用调用同版本的多部件文件上传API时,返回400 Bad Request错误,但curl和Angular的POST请求均可正常调用该API。

WebClient端原代码

var home = "/home/me";

var uploadFile = new File(home+"/upload.csv");   
var uploadPath = uploadFile.toPath();
var uploadContent = Files.readString(uploadPath);

var multipartBodyBuilder = new MultipartBodyBuilder();
multipartBodyBuilder.part("file", uploadPath);
//multipartBodyBuilder.part("file", uploadFile);
var mimeMultipartData = multipartBodyBuilder.build();

var configuration = new Configuration(/* ... */);

var webClient = WebClient.builder()
        .baseUrl(_baseUrl(configuration.getEndpoint()))
        .filters( filters -> {
            filters.add(authentication(configuration));

            if (configuration.capturePackets()) {
                filters.add(captureRequest());
                filters.add(captureResponse());
            }
        })
        .build();

Mono<HttpStatus> httpStatusMono = webClient
     .post()
     .uri(URI.create("http://localhost:8080/api/uploads"))
     .body(BodyInserters.fromMultipartData(mimeMultipartData))
     .retrieve()
     .bodyToMono(HttpStatus.class);

服务端API代码

@PostMapping("/uploads")
public ResponseEntity<?> uploads(@RequestParam(value="file", required=true) MultipartFile file) throws IOException {
    try (InputStream input = file.getInputStream()) {
        doSomething(input);
    }
    return ResponseEntity.ok().build();
}

错误信息

org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from POST http://localhost:8080/api/uploads
    at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:217)
    Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ 400 from POST http://localhost:8080/api/uploads [DefaultWebClient]
Original Stack Trace:
        at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:217)
        ...(省略部分栈信息)

正常调用示例

curl命令

curl -X POST -v --user "username:password" -H "Content-Type: multipart/form-data" \
     --form file=@upload.csv  http://localhost:8080/api/uploads

Angular代码

upload(file: File): Observable<any> {
    const formData: FormData = new FormData()

    formData.append('file', file, file.name);

    const observable: Observable<any> = this._http
      .post(url, formData)
      .pipe(
        // map(response => response),
        share()
    );

解决方案

问题根源是WebClient构建多部件请求时,直接传入Path对象无法被Spring正确识别为文件资源,导致服务端无法解析出MultipartFile。调整方式如下:

调整后的WebClient代码

var home = "/home/me";
var uploadFile = new File(home + "/upload.csv");

var multipartBodyBuilder = new MultipartBodyBuilder();
// 方式1:直接传入File对象,自动处理文件名与内容类型
multipartBodyBuilder.part("file", uploadFile)
                    .contentType(MediaType.MULTIPART_FORM_DATA);

// 方式2:用FileSystemResource包装Path,手动指定文件名(适合需要自定义文件名的场景)
// multipartBodyBuilder.part("file", new FileSystemResource(uploadFile.toPath()))
//                     .filename(uploadFile.getName())
//                     .contentType(MediaType.TEXT_PLAIN); // 根据实际文件类型调整

var mimeMultipartData = multipartBodyBuilder.build();

var configuration = new Configuration(/* ... */);

var webClient = WebClient.builder()
        .baseUrl(_baseUrl(configuration.getEndpoint()))
        .filters( filters -> {
            filters.add(authentication(configuration));

            if (configuration.capturePackets()) {
                filters.add(captureRequest());
                filters.add(captureResponse());
            }
        })
        .build();

// 服务端返回无body响应,用toBodilessEntity()替代bodyToMono(HttpStatus.class)更合理
Mono<ResponseEntity<Void>> responseMono = webClient
     .post()
     .uri("http://localhost:8080/api/uploads")
     .body(BodyInserters.fromMultipartData(mimeMultipartData))
     .retrieve()
     .toBodilessEntity();

关键调整说明

  1. 正确传递文件资源:必须使用File或FileSystemResource包装文件路径,Spring才能生成符合多部件规范的请求体,包含必要的文件名和内容类型标识。
  2. 响应处理优化:服务端返回的是无内容响应,使用toBodilessEntity()可以避免解析空body时的潜在异常。
  3. URI简化:直接传入字符串URI即可,无需手动创建URI对象,WebClient会自动处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:45:45