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

使用MultipartEntityBuilder发请求却收到application/json的问题排查

问题:Apache HttpClient发送Multipart请求时Content-Type异常导致415错误?

客户端代码(Apache HttpClient)

CloseableHttpClient client = HttpClients.createDefault();
URIBuilder builder = new URIBuilder(uri);
HttpPost request = new HttpPost(builder.build().toString());
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.addTextBody("user", username)); // 存在语法错误:多余的右括号
multipartEntityBuilder.addTextBody("pass", password)); // 存在语法错误:多余的右括号
multipartEntityBuilder.setContentType(ContentType.MULTIPART_FORM_DATA);
multipartEntityBuilder.setCharset(StandardCharsets.UTF_8);
request.setEntity(multipartEntityBuilder.build());
HttpResponse response = client.execute(request);

API端点代码(JAX-RS)

@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response authenticateUser(@FormParam("user") String username, 
                                 @FormParam("pass") String password) {
    try {
        String token = authenticate(username, password);
        return Response.ok(token).build();
    } catch (Exception e) {
        return Response.status(Response.Status.FORBIDDEN).build();
    }
}

问题现象

API日志显示请求的Content-Type为application/json而非预期的multipart/form-data,触发415(不支持媒体类型)错误。但使用Spring RestTemplate的调用方式可正常请求该API。


原因分析

  1. 代码语法错误:HttpClient代码中addTextBody方法调用末尾多了一个右括号,这会导致编译失败;若强行运行,会导致MultipartEntityBuilder构建实体异常,HttpClient可能 fallback 到默认的Content-Type(比如application/json)。
  2. 错误设置ContentType:手动调用multipartEntityBuilder.setContentType(ContentType.MULTIPART_FORM_DATA)是冗余且可能产生干扰的——MultipartEntityBuilder默认会构建multipart/form-data类型的实体,且会自动生成必要的boundary参数(比如multipart/form-data; boundary=xxxx),手动设置会覆盖自动生成的完整Content-Type,甚至导致头信息不完整。
  3. 请求头被覆盖:若代码中存在拦截器或其他逻辑修改了HttpPost的请求头,可能会将Content-Type替换为application/json。

排查与解决步骤

  • 修复语法错误:移除addTextBody调用末尾多余的右括号,确保代码正常编译:
    multipartEntityBuilder.addTextBody("user", username);
    multipartEntityBuilder.addTextBody("pass", password);
    
  • 移除冗余的ContentType设置:删除multipartEntityBuilder.setContentType(ContentType.MULTIPART_FORM_DATA),让MultipartEntityBuilder自动生成包含boundary的完整Content-Type头。
  • 验证实体的Content-Type:在设置请求实体前,打印实体的ContentType确认格式:
    HttpEntity entity = multipartEntityBuilder.build();
    System.out.println(entity.getContentType()); // 应为类似 multipart/form-data; boundary=... 的格式
    
  • 检查请求拦截器:排查是否存在HttpRequestInterceptor或其他逻辑修改了请求头,确保没有覆盖Content-Type。
  • 升级HttpClient版本:若使用旧版本(如4.3及以下),可能存在MultipartEntityBuilder的bug,建议升级到4.5.x及以上版本。

为什么RestTemplate可以正常工作

RestTemplate的处理逻辑更严谨:

  • 显式设置HttpHeaders的ContentType为MULTIPART_FORM_DATA,当请求体为MultiValueMap时,会自动使用MultipartFormHttpMessageConverter处理请求。
  • 该转换器会自动生成合法的boundary参数,并构建包含boundary的完整Content-Type头,确保请求头与请求体格式匹配,不会出现不兼容的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 01:59:52