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!"); } }
问题原因
- 浏览器请求中断:当服务器返回
413 Payload Too Large时,浏览器可能直接中断未完成的文件上传请求,导致fetch无法解析响应体,直接进入catch块但无法获取后端返回的自定义错误信息。 - 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
相关产品推荐
相关产品推荐

