解决SpringBoot文件上传异常提示The temporary upload location xxx is not valid

在用SpringBoot搭建的服务时,如果你用到了文件上传类型的接口的话,可能会遇到今天说的这个坑:

之前部署到服务器上的SpringBoot应用一直工作得好好的,而且上传文件的接口之前也一直好好的,都没问题;

但是有一天突然发现调用上传文件的接口失败,出现了类似以下的提示

The temporary upload location [/tmp/tomcat.4232587034585098924.8083/work/Tomcat/localhost/ROOT] is not valid

具体如下:

java.io.IOException: The temporary upload location [/tmp/tomcat.4232587034585098924.8083/work/Tomcat/localhost/ROOT] is not valid
	at org.apache.catalina.connector.Request.parseParts(Request.java:2843)
	at org.apache.catalina.connector.Request.parseParameters(Request.java:3216)
	at org.apache.catalina.connector.Request.getParameter(Request.java:1137)
	at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:75)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

一、问题分析

从打印的异常信息来看,问题比较清晰,这个目录is not valid,就是非法无效的意思

根据异常信息里的文件路径,试着去查看下这个目录,结果发现,没有这个目录(小朋友你是否有很多问号?)

哈哈哈。

带着众多的问号,接着分析:这个目录到底是干啥用的?为什么需要这个目录?

先简单描述一下原因:因为SpringBoot上传的文件时,会缓存到本地磁盘,而缓存的路径就是上面说的那个路径

接着引入的疑问就是:为什么要缓存到本地的临时文件?

因为流读取一次消费之后,后面无法再从流中获取数据,所以缓存到临时目录里,方便后续复用,这个感兴趣的话,可以打断点跟一下Spring的源码。

那又有一个问题,之前上传接口能用,也就是说之前这个临时目录是有的,那为什么现在这个临时目录忽然不在了?

Springboot项目启动时会创建一个/tmp/tomcat.xxxx.xxx/work/Tomcat/localhost/ROOT的临时目录,作为文件上传的临时目录

但是该目录会在n天之后被系统自动清理掉,这个清理是由linux操作系统完成的

知道了这些后,那咱们的问题怎么解决呢?

二、解决方案

方法1、重启应用

因为这个临时目录是在Springboot项目启动时创建的,所以,再重启一下服务就会再次重新创建一个目录

但是这个方法治标不治本,所以不推荐

方法2、增加服务配置,自定义baseDir

在Springboot配置文件里自定义一个不会被定时删除的文件目录,这样就不会被定时的删除了

server.tomcat.basedir=/tmp/tomcat

方法3、注入bean,手动配置临时目录

@Bean
MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    factory.setLocation("/tmp/tomcat");
    return factory.createMultipartConfig();
}

这个和方法2差不多,都是自定义一个目录,不被删除

方法4、配置不删除tmp目录下的缓存目录

vim /usr/lib/tmpfiles.d/tmp.conf

# 最后添加一行
x /tmp/tomcat.*

比较推荐最后一种方法,比较简单通用

好了,以上就是这个问题的解决办法了,get到以后,可以去试试了。

如果觉得本文对你有帮助的话,可以点个关注,点个赞!感谢

猜你喜欢

转载自blog.csdn.net/ju_362204801/article/details/106928521