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

