闲话
写下这篇笔记,同时带给大家一段话,摘自某位大佬(我记不清楚是谁了哈哈哈):
最难找的 bug 往往是最低级的错误。
这段话总能让学习阶段的我排错后分析问题原因时受益匪浅。
正文
前言
个人项目开发需要完成一个文件上传删除下载的功能,这本该是简单的事情,但是却阻挠了我许久,让我的项目进度迟迟不动。当然也是因为最近事情多,但外界的事情并不是借口。。好了闲话少说,先贴一下问题
问题
问题 1:请求携带文件大小超出默认限制范围
首先是文件大小的问题,springboot 项目出现 MaxUploadSizeException 异常。springboot 默认上传文件大小限制是 1MB,默认单次请求大小限制是 10MB,超出大小就会抛出上述异常。而请求文件大小超过 1MB 和超过 10MB时的异常是不同的:
超过 1MB 时异常信息
Resolved [org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.]
超过 10MB 时异常信息
Resolved [org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (12209424) exceeds the configured maximum (10485760)]
当文件超过 10MB 时项目报错,而这一异常却无法被自定义的全局异常处理器@ControllerAdvice捕获,页面直接报 500
原因
下图是 SpringMVC 的单次请求响应流程
这张图就解释了我们在 Controller 里无法捕获异常的原因。是因为 MultipartException在前两个阶段就被捕获并抛出了(并有return值),并未到达Controller层。这里也是为什么我们设置了全局捕获,可以捕获 MultipartException 异常却无法正确返回对象给前端的原因(return值被提前处理)。
解决
解决方法在摘录的大佬的文章中展示了两种,我用了最简洁方便的一种:
在工程的配置文件 application.yml 中配置请求大小限制和上传文件大小限制,以及tomcat的最大吞吐量
spring:
servlet:
multipart:
max-file-size: 5MB
max-request-size: 20MB
server:
port: 8999
tomcat:
# 当文件超过tomcat的大小限制后会先于Controller触发异常,此时我们的异常处理器无法捕获异常
max-swallow-size: 30MB # 内嵌tomcat的最大吞吐量,设置 -1 不限制
问题2:上传文件接口和请求未遵循必须条件
第二个问题出现在上传文件的前后端接口联调,下面是异常信息:
org.springframework.web.multipart.MultipartException: The current request is not a multipart request
原因
最可能犯的错误的原因和解决方法我学习总结有以下几点
1. 请求方式必须为 post
2. 请求的contentType 必须设置为以 "multipart/" 开头
3. 后端接口的接收参数需要用 @RequestParam 指定表单的key,用于接收文件数据
解决
要点如下
前端代码:
注意这第三张图!!
后端接口
@RestController @RequestMapping("/file") @Slf4j public class FileWorkerController { @PostMapping("upload") @ResponseBody ResultVO<String> uploadAndSaveForImage(@RequestParam("file") MultipartFile file) { log.info("multipart ==> {}", file); return ResultVO.ok(); } }
学习自大佬文章:http://t.csdn.cn/LYbHF
在此表示晚辈的万分感激!
个人问题
那么我的弱智问题是在哪里呢?实际上就是在前端代码中,我封装了FormData对象,传递的却是文件file。。。无语。。
后话
所以说细节决定成败,最难找的 bug 或许出现在最低级的操作中。当你发现查遍所有资料和主要问题都没有解决时,就该找找自己的问题了。当然也可以自一开始就先注意看看是不是自己的问题。在这里我也借此警醒自己,保持谦卑,砥砺前行!!
如果有其他意见和看法,欢迎各位评论区留言!如果有其他合作或者交流的意向,也欢迎私信我!