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

使用RestTemplate POST大字节数组到API 超4MB报500错误如何修复

问题修复方案

你遇到的超4MB文件上传报500错误,核心触发点有三个:

  1. Spring Boot内嵌Tomcat默认限制了multipart上传的文件大小,未做自定义配置时单文件默认上限为1MB,你当前环境可传4MB属于手动调整过阈值但未覆盖大文件场景;未配置异常处理时,文件超限抛出的MaxUploadSizeExceededException会直接返回500状态码,而非标准的413错误。
  2. 服务端Controller直接用byte[]接收文件参数,会将整个文件全量加载到JVM堆内存,大文件场景下容易触发内存溢出或参数解析失败。
  3. 客户端RestTemplate构造multipart请求时未指定正确的请求头,直接传字节数组的方式无法被服务端识别为文件参数,且未调整大文件场景下的超时配置。

服务端(Controller侧)修复

1. 放开上传大小限制

在服务端的application.yml中添加以下配置,具体阈值按业务需求调整:

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 100MB # 单文件最大支持100MB
      max-request-size: 110MB # 整个请求最大大小,需预留其他表单参数的空间
      file-size-threshold: 2MB # 超过2MB的文件直接写入临时磁盘,不驻留内存
server:
  tomcat:
    max-http-form-post-size: 110MB # 放开Tomcat本身的POST表单大小限制,和上面的请求大小保持一致

如果是properties格式配置,对应参数为:

spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=110MB
spring.servlet.multipart.file-size-threshold=2MB
server.tomcat.max-http-form-post-size=110MB

2. 调整接口接收方式

不要直接用byte[]接收文件,改用MultipartFile对象,直接获取流做S3上传,避免全量文件加载到内存:

@PostMapping("/upload")
public void uploadToS3(@RequestParam String bucket, @RequestParam String key, @RequestParam MultipartFile file) throws IOException {
    // 直接传入输入流到S3上传逻辑,不需要将整个文件转为字节数组
    dataJockeyService.uploadFile(bucket, key, file.getInputStream());
}

对应Service层的uploadFile方法调整为接收InputStream类型参数,对接S3 SDK的流式上传接口即可。


客户端(RestTemplate侧)修复

调整RestTemplate的请求构造逻辑,正确设置multipart请求头,用资源对象传文件,同时调大超时时间适配大文件传输:

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false); // 关闭请求体缓冲,大文件直接流式传输
requestFactory.setConnectTimeout(10000); // 连接超时10秒
requestFactory.setReadTimeout(120000); // 读超时调整为2分钟,适配大文件上传耗时
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(requestFactory);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA); // 必须指定multipart表单类型

MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("bucket", datajockeys3bucket.replace(sing_env,env));
String fileName = sampleFile.substring(sampleFile.lastIndexOf("/") + 1);
paramMap.add("key", "clone/".concat(fileName));
// 构造字节数组资源,不要直接传入原生byte数组
paramMap.add("file", new ByteArrayResource(sampleFileArray) {
    @Override
    public String getFilename() {
        // 必须返回文件名,否则服务端会将该参数识别为普通表单参数,而非文件
        return fileName;
    }
});

HttpEntity<MultiValueMap> request = new HttpEntity<>(paramMap, headers);
restTemplate.exchange(
    dataJockeyUrl.replace(sing_env,env).concat("/upload"),
    HttpMethod.POST,
    request,
    Void.class
);

如果需要传输100MB以上的文件,建议将SimpleClientHttpRequestFactory替换为Apache HttpComponents实现的HttpComponentsClientHttpRequestFactory,对大文件流式传输的稳定性更好。


GB级大文件优化方案

如果需要传输几百MB到GB级的文件,上述方案会因为文件经过应用服务器中转导致带宽占用高、易超时,建议改用两种方案:

  • 分片上传:客户端将文件切为5MB~10MB的固定分片,逐个调用接口上传分片,所有分片上传完成后服务端调用S3的分片合并接口完成上传,支持断点续传,失败仅需重传出错分片。
  • 客户端直传S3:服务端仅负责向客户端签发S3的STS临时上传凭证,客户端拿到凭证后直接将文件上传到S3,完全不经过应用服务器,性能最优,也没有应用侧的文件大小限制。

内容的提问来源于stack exchange,提问作者Arjun C E

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 18:24:46