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

React+SpringBoot上传大文件:捕获MaxUploadSizeExceededException后前端无响应

大文件上传时前端无法接收Spring Boot返回的自定义错误响应

问题场景

ReactJS前端 + Spring Boot后端应用,大文件上传时出现以下异常:

  • 后端已通过@RestControllerAdvice捕获MaxUploadSizeExceededException,返回413 Payload Too Large状态码和自定义错误文本
  • 前端使用fetch发起请求时,无法获取该错误响应;小文件上传正常,且Postman可正确接收后端返回的错误信息

前端上传代码

const uploadHandler = async () => {
  if (!acceptedFiles?.length) {
    return;
  }
  setIsLoading(true);

  const formData = new FormData();
  for (let i = 0; i < acceptedFiles.length; i++) {
    formData.append('files', new File([acceptedFiles[i]], parentDir + acceptedFiles[i].name));
  }

  await fetch(`/api/filemanager/${encodeURIComponent(filemanager)}/files`, {
    method: 'POST',
    body: formData,
  })
    .then((response) => {
      setIsLoading(false);
      if (response.ok) {
        return response;
      } else {
        throw new Error(`Request failed with status: ${response.status}, and message: ${response.statusText}`);
      }
    })
    .then(() => {
      onComplete();
    })
    .catch((error) => {
      setIsLoading(false);
    });
};

后端异常捕获代码

@RestControllerAdvice
public class AdviceController {
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<String> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException exc) {
        return ResponseEntity
            .status(HttpStatus.PAYLOAD_TOO_LARGE)
            .body("File upload failed: File too large!");
    }
}

问题原因

  1. 浏览器请求中断:当服务器返回413 Payload Too Large时,浏览器可能直接中断未完成的文件上传请求,导致fetch无法解析响应体,直接进入catch块但无法获取后端返回的自定义错误信息。
  2. Spring Boot解析时机:默认情况下,MultipartResolver会在请求到达控制器之前解析文件上传请求,此时触发的MaxUploadSizeExceededException可能被Servlet容器(如Tomcat)拦截,返回容器默认错误页而非Spring的自定义响应。

解决步骤

1. 调整Spring Boot配置,确保异常被全局处理器捕获

在application.properties中添加以下配置:

# 单个文件大小限制(根据需求调整)
spring.servlet.multipart.max-file-size=10MB
# 总上传请求大小限制
spring.servlet.multipart.max-request-size=10MB
# 延迟Multipart解析,让请求先到达控制器,确保全局异常处理器能捕获异常
spring.servlet.multipart.resolve-lazily=true

2. 修改前端fetch逻辑,完善错误处理

优化uploadHandler代码,区分网络中断错误和业务错误,并正确读取响应体:

const uploadHandler = async () => {
  if (!acceptedFiles?.length) {
    return;
  }
  setIsLoading(true);

  const formData = new FormData();
  for (let i = 0; i < acceptedFiles.length; i++) {
    formData.append('files', new File([acceptedFiles[i]], parentDir + acceptedFiles[i].name));
  }

  try {
    const response = await fetch(`/api/filemanager/${encodeURIComponent(filemanager)}/files`, {
      method: 'POST',
      body: formData,
    });
    
    if (response.ok) {
      onComplete();
    } else {
      // 读取后端返回的自定义错误文本
      const errorMsg = await response.text();
      throw new Error(errorMsg || `Upload failed with status: ${response.status}`);
    }
  } catch (error) {
    if (error instanceof TypeError) {
      // 处理网络中断类错误(大概率是文件过大导致请求被浏览器中断)
      console.error('Upload failed: File may be too large or network error occurred');
      // 可在此处提示用户文件大小超出限制
    } else {
      // 展示后端返回的自定义错误信息
      console.error('Upload failed:', error.message);
    }
  } finally {
    // 确保加载状态始终被重置
    setIsLoading(false);
  }
};

3. 可选:配置Servlet容器错误处理(若上述步骤无效)

如果Spring的全局异常处理器仍未捕获异常,可能是Tomcat等容器先拦截了错误,可添加以下配置让容器将错误转发给Spring处理:

server.error.include-message=always
server.error.path=/error

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:02:03