Spring Boot项目部署在Linux服务器运行一段时间后,用户在上传附件时会提示error(如果开发人员设置了错误提示语,则提示对应message)。
进入Linux服务器。查看项目运行日志。发现有如下错误提示:
java.io.IOException: The temporary upload location [/tmp/tomcat.595585555590026.8081/work/Tomcat/localhost/ROOT] is not valid
at org.apache.catalina.connector.Request.parseParts(Request.java:2839) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.connector.Request.parseParameters(Request.java:3211) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.connector.Request.getParameter(Request.java:1137) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:75) ~[spring-web-4.3.13.RELEASE.jar!/:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar!/:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.13.RELEASE.jar!/:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar!/:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) ~[spring-boot-actuator-1.5.9.RELEASE.jar!/:1.5.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar!/:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_11]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_11]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar!/:8.5.23]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_11]
根据错误提示可知:临时上传目录[/tmp/tomcat.5955857058409590026.8081/work/Tomcat/localhost/ROOT]不存在。
我们可以进入tmp目录查看该目录是否存在,如下图所示:
查看上图发现tomcat.5955857058409590026.8081目录确实不存在。因此在上传附件时会提示错误。
问题原因已查明,现在需要对问题进行修复。修复方法如下所示:
方法1、重新运行Spring Boot项目【即重新执行:java -jar springBootDemo.jar】。该方法简单粗暴,可快速解决上传失败问题。
但该解决方法会有以下问题:
a、该方法在生产环境下会造成用户体验不好。如果用户正在使用该系统,而你在重启系统,就会造成数据的丢失。
b、方法1治标不治本。待项目再次运行一段时间后,会发现附件上传失败问题会再次出现。
结合上面两点,方法1不是最佳选择。
方法2、直接在项目配置文件中指定默认路径:
修改配置文件application.yml
server:
tomcat:
basedir: "\Temp\springBootDemo"
如果配置文件为application.properties。则如下设置
server.tomcat.basedir="\Temp\springBootDemo"
配置文件修改后,重新将该项目打包成jar包拷贝至服务器中,待用户空闲时间进行发布。该方法可永久解决该问题。
方法3、在项目启动类中新增如下代码:
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
// 为解决附件上传失败问题,添加以下Bean
// 自定义上传文件的临时目录
@Bean
MultipartConfigElement multipartConfigElement(){
MultipartConfigFactory configFactory = new MultipartConfigFactory();
String location = "\Temp\springBootDemo"; // 临时目录地址
File filePath = new File(location);
if (!filePath.exists()) {
filePath.mkdirs(); // 如果目录不存在,则新建
}
configFactory.setLocation(location);
return configFactory.createMultipartConfig();
}
}
【以上三点目的是在程序上做出改变以此来解决问题】
该问题产生的原因是Linux服务器中tmpwatch命令。如果设置了该命令。在设置时间范围内,如果未对该文件进行相应操作,系统会自动删除该文件。
方法4、基于上述语句。找到tmpwatch文件,修改该文件即可。
1 #! /bin/sh
2 flags=-umc
3 /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \
4 -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \
5 -X '/tmp/hsperfdata_*' 10d /tmp
6 /usr/sbin/tmpwatch "$flags" 30d /var/tmp
7 for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do
8 if [ -d "$d" ]; then
9 /usr/sbin/tmpwatch "$flags" -f 30d "$d"
10 fi
11 done
通过上述文件第5行代码中可以获取到【10d /tmp】表明10天内tmp目录下有文件未进行过任何操作,则系统会自动删除对应目录。而spring boot项目启动时默认上传路径就在tmp目录下。因此我们对该文件进行修改,注释第3-5行的代码即可。