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

Spring Boot 3.3.3升级后RestTemplate上传PDF报400错误求助

Spring Boot 3.3.3升级后RestTemplate上传PDF报400错误(Stream ended unexpectedly)

问题背景

将Spring Boot从3.1.11版本升级至3.3.3版本后,使用RestTemplate上传PDF文件时出现异常,API调用返回400 BAD_REQUEST,错误详情显示Stream ended unexpectedly。相同代码在3.1.11版本下可正常运行,排除服务端问题。

请求头信息

  • contentType: multipart/form-data
  • contentLength: 手动设置为文件字节数组长度

请求实体构建代码

headers.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(bytes.length));

MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
ByteArrayResource byteArrayResource = new ByteArrayResource(bytes, "Pdf name") {
    @Override
    public String getFilename() {
        return filename;
    }
};
parts.add("data", byteArrayResource);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

RestTemplate调用代码

exchange(uri, "POST", requestEntity, String.class);

异常栈信息

at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:103) ~[spring-web-6.1.12.jar:6.1.12]
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:183) ~[spring-web-6.1.12.jar:6.1.12]
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:137) ~[spring-web-6.1.12.jar:6.1.12]
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) ~[spring-web-6.1.12.jar:6.1.12]
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:942) ~[spring-web-6.1.12.jar:6.1.12]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:891) ~[spring-web-6.1.12.jar:6.1.12]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:790) ~[spring-web-6.1.12.jar:6.1.12]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:672) ~[spring-web-6.1.12.jar:6.1.12]

RestTemplate实例构建代码

SSLContext sslContext = sslContextBuilder.build();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("****", "****");
keyManagerFactory.init(clientStore, *****);
sslContext.init(keyManagerFactory.getKeyManagers(), null, ****);

SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(socketFactory).build();

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));

注:sslContextBuilder已配置TLS协议及必要证书,相关代码因安全和简洁性省略。

解决方案

原因分析

Spring Boot 3.3.x对应Spring Framework 6.1.x,其中HttpComponentsClientHttpRequestFactory处理multipart请求时,若手动设置Content-Length头,会与实际multipart请求的总长度(包含boundary等额外内容)不匹配,导致服务端接收时流提前结束。旧版本Spring Framework对该情况兼容性更好,或multipart编码逻辑存在差异。

修复步骤

移除手动设置的Content-Length请求头,由Spring自动计算并设置正确的内容长度:
删除请求实体构建代码中的以下行:

headers.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(bytes.length));

额外优化(可选)

可改用MultipartBodyBuilder构建请求实体,Spring会自动处理请求头及内容长度,代码示例:

MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("data", byteArrayResource);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(builder.build(), headers);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:46:21