大家都知道,现在SpringBoot框架,已经是非常流行的Java快速开发框架,替代了以前传统的SSM/SSH时代的XML配置,零XML配置就可以跑起一个jar企业应用,只需要通过各种“注解”来进行配置。而且SpringBoot内部集成了Tomcat/Undertow的Web服务器,不需要在以前一样,先要在服务器上放一个Tomcat/Undertow,然后在项目打成war包放到容器里进行运行,无论从使用上,效率上都提升了很多。
虽然SpringBoot做了很多简化,但还是基于spring、springmvc、web相关框架的那些类及API,还是要有了解,不然有进也会遇到不可预知的“坑”。为了便于后人,顺便把这些整理成文章。
一、问题产生的背景
今天小伙伴写的一个系统,是基于SpringBoot,业务人员在操作时,发现上不传了图片/文件,业务人员说之前是可以上传,不知为什么今天上传不了。
二、问题的分析
既然发现了问题,那就从程序输出的日志上找原因吧,找到服务对应的日志,通过简单的grep命令,找到如下一段异常:
org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request;
nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.1312576899112123874.8089/work/Tomcat/localhost/ROOT] is not valid
如图所示:
这个错误提示是:“临时上传的目录非法”。小伙伴很奇怪,项目里明明没有配置这个目录,为什么会用到这个目录呢?
原来,SpringBoot框架中在上传附件时,会先缓存到本地磁盘上(注意:http流是一次消费的,后续无法在次使用,所以要先缓存起来),以便后续的复用。而在没有明确指定缓存的目录时,SpringBoot默认是在/tmp目录下的。
从这个报错看是这个目录可能不存在/或者权限不够之类。进入服务器后,结果发现没有这个目录,为什么这个目录会不见了呢?
查找linux的资料,发现linux有这样的机制:
在linux中,tmp目录可以删除;该目录用于存储临时性的文件,该目录会默认清理指定天数未用的文件,系统重启会清空目录,“/tmp”目录默认清理10天未用的文件,“/var/tmp”目录默认清理30天未用的文件。
三、解决的办法
既然知道了问题的原因,针对这个问题有多种解决办法。
1、 临时解决办法(不便于及时改配置部署)
重启下应用服务,让应用服务重新生成目录(SpringBoot中的tomcat在重启后,会在/tmp目录下,重新生成一个临时的目录) -- 但以后还是会面临时被清除。
2、 修改linux的配置,让其不清除这类文件(可能会堆积,不建议)
vim /usr/lib/tmpfiles.d/tmp.conf
# 添加下面一行
/tmp/tomcat.*
3、 增加启动参数
启动springBoot程序,添加使用指定临时目录的启动参数 -java.tmp.dir=你想的目录
4、修改SpringBoot的properties文件
找到项目的application.properties文件,在基中添加以下配置,让其使用其他目录,不使用/tmp目录
server.tomcat.basedir=你想的目录
或
spring.http.multipart.location=你想的目录
好了,至此,上传的临时目录问题解决。看到此文章的小伙伴,可收藏起来,以备后续之需,必竟在做系统的过程中,上传图片/附件是很常见的功能。