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

如何通过RestTemplate上传大文件?2GB以上文件报ArrayIndexOutOfBoundsException

解决方案:RestTemplate转发大文件(>2GB)的数组越界及501编码问题

一、解决ArrayIndexOutOfBoundsException(大文件数组越界)

问题原因

默认RestTemplate使用AbstractBufferingClientHttpRequest,会将整个请求体缓冲到FastByteArrayOutputStream中。而Java字节数组的最大长度为Integer.MAX_VALUE(约2GB),当文件超过该阈值时,就会触发数组越界异常。

解决步骤

替换RestTemplate的请求工厂为非缓冲类型,比如Apache HttpClient的HttpComponentsClientHttpRequestFactory,它支持流式传输,无需将整个文件加载到内存:

  1. 添加Apache HttpClient依赖(Maven示例):
<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.2.3</version>
</dependency>
  1. 重新配置RestTemplate,使用非缓冲请求工厂:
@Bean
public RestTemplate largeFileRestTemplate() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(HttpClients.createDefault());
    // 禁用请求体缓冲,启用流式传输
    factory.setBufferRequestBody(false);
    RestTemplate restTemplate = new RestTemplate(factory);
    // 按需保留日志拦截器
    restTemplate.setInterceptors(Collections.singletonList(new LoggingInterceptor()));
    return restTemplate;
}
  1. 调整上传代码,传递文件准确长度(避免分块编码):
    如果从MultipartFile获取文件,直接传递输入流和文件大小:
protected String postFileRestTemplate(String addToBaseURL, MultipartFile file) throws IOException {
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

    MultipartBodyBuilder builder = new MultipartBodyBuilder();
    builder.part("content", "iso");
    // 传递流时指定文件长度,让HttpClient自动设置Content-Length
    builder.part("filename", file.getInputStream(), file.getSize());

    MultiValueMap<String, HttpEntity<?>> build = builder.build();
    HttpEntity<Object> objectHttpEntity = new HttpEntity<>(build, httpHeaders);

    ResponseEntity<String> exchange = restTemplate.postForEntity(
            baseURL + addToBaseURL,
            objectHttpEntity,
            String.class);

    log.info(exchange.getBody());
    return exchange.getBody();
}

二、解决"501 chunked transfer encoding not supported"错误

问题原因

移除LoggingInterceptor后,默认请求工厂会自动启用分块编码(chunked),但目标API不支持该传输方式。而日志拦截器可能因提前读取请求体,触发了RestTemplate自动缓冲,从而绕过了分块编码。

解决步骤

结合上述非缓冲请求工厂配置,同时确保请求能正确设置Content-Length头:

  • 使用HttpComponentsClientHttpRequestFactory并禁用缓冲后,只要传递了文件的准确长度,HttpClient会自动生成Content-Length头,避免使用分块编码。
  • 如果无法获取文件长度(如流来自网络),需让目标API升级支持分块编码,或改用其他大文件传输协议(如FTP)。

关键注意事项

  • 优先使用Apache HttpClient的请求工厂,而非默认的SimpleClientHttpRequestFactory,前者对大文件流式传输的支持更稳定。
  • 必须确保传递给MultipartBodyBuilder.part()的资源包含准确长度,否则仍会触发分块编码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:48:10