背景

公司的 springboot 项目,上传图片报错:

在这里插入图片描述
在项目的 application.properties 中配置:

#上传文件大小(字节)设置为 1mb
zfzz.file.upload.maxFileSize=1
#系统默认为1MB
spring.servlet.multipart.maxFileSize=1MB
spring.servlet.multipart.maxRequestSize=1MB

分析

首先下载依赖源码文件:

在这里插入图片描述

点击错误提示定位到抛出异常位置:

在这里插入图片描述

打一个断点,然后重新请求,观察 debug 模式下的调用链:

没有发现什么头绪

继续观察异常日志信息
在这里插入图片描述
越是最下面的异常,越是最实际报错的位置,于是定位到了这里:

在这里插入图片描述
继续打断点看到异常信息中的数值:

在这里插入图片描述

解决

下面就看 sizeMax 大小的定义和由来了,具体就是 org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl 这个类;

sizeMaxFileItemIteratorImpl 类的一个属性;并且只有一个构造方法;在这里插入图片描述

在这里插入图片描述

首先在此处打一个断点,重发请求,观察调用链:

在这里插入图片描述

发现实际的相关联的类是 org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload

想来初始化的时候,肯定要使用构造方法,所以在它的两个构造方法上都打了断点,重新请求,定位到无参构造方法:

在这里插入图片描述

查看调用链的上一步,发现实际赋值和 upload.setFileSizeMax(mce.getMaxFileSize()); 这句代码有关:
在这里插入图片描述

好了现在,查看 mce 的定义:

在这里插入图片描述

我没有查看 getWrapper().getMultipartConfigElement(); 代码的内容,springboot 的 bean 对象大概率就一个,所以我就直接看 mce 的定义类 javax.servlet.MultipartConfigElement 的信息;

在这里插入图片描述

没错,我又在它的每个构造函数中打断点,重新请求,并且定位到了第二个构造方法:

说明一下,刚开始并没有走到第二个构造方法的断点处,想来之前上面的操作每个请求都会生成一个新的对象,而这个 org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload 很大概率项目启动就实例化了,而且只有一个,所以我重启项目,于是走到了第二个构造函数:

在这里插入图片描述

尝试查看调用链:

在这里插入图片描述
convertToBytes 函数很简单,有就返回第一个参数值,没有就返回第二个参数值;

调用链在网上一步:

在这里插入图片描述
可以看到 org.springframework.boot.autoconfigure.web.servlet.MultipartProperties 这个类有点像 Multipart(上传) 的配置文件,本来不确定,但是查看这个类,发现类上面有注解:

在这里插入图片描述
@ConfigurationProperties 是 springboot 读取 application.properties 用的,是 @Value 的 plus 版;

自此从异常的开始到是否与我们的

#上传文件大小(字节)设置为 1mb
zfzz.file.upload.maxFileSize=1
#系统默认为1MB
spring.servlet.multipart.maxFileSize=1MB
spring.servlet.multipart.maxRequestSize=1MB

application.properties 配置关系就对应上了。

学习到了一些东西

查看并且实践:

在这里插入图片描述
即,spring.servlet.multipart.maxFileSize 是单个文件的最大值,spring.servlet.multipart.maxRequestSize 是整个请求的最大值。

我的请求中包含一个图片和一个 .zip 压缩包 ,他们都是 file ,就是 maxFileSize,每个想设置 3 M 的话,那么我的 spring.servlet.multipart.maxFileSize 应该是 3M,而整个请求 spring.servlet.multipart.maxRequestSize 应该要比 (3+3) M 更大一点,因为除了图片和压缩包,还有一些类似名称、性别的小参数,肯定要比 (3+3)M 大一点,那就设置成 7 M 吧;

最后的 application.properties

#上传文件大小(字节)设置为 3mb # 这是代码中的自己写代码时校验用的参数,可以忽略不看
zfzz.file.upload.maxFileSize=3
#系统默认为1MB
spring.servlet.multipart.maxFileSize=3MB
spring.servlet.multipart.maxRequestSize=7MB
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐