2023.11.30 | admin | 66次围观
异常描述
春节过后,生产报了个异常:
主要是这句:The temporary upload location …… is not valid !临时的上传路径不可用,在服务器上找了一下,这个路径确实不存在,应该是文件丢失了
处理异常 异常原因
SpringBoot项目启动后,系统默认会在 /tmp 目录下自动创建如下三个目录:
hsperfdata_root,
tomcat.************.8080,(结尾是项目的端后)
tomcat-docbase.*********.8080
注: Multipart(form-data)的方式处理请求时,默认就是在第二个目录下创建临时文件的
CentOS7会定期自动清理/tmp路径下的文件,清理规则如下:
[eccore@vm035vmt006 /]$ cat /usr/lib/tmpfiles.d/tmp.conf
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
# See tmpfiles.d(5) for details
# Clear tmp directories separately, to make them easier to override
v /tmp 1777 root root 10d # 清理/tmp下10天前的目录和文件
v /var/tmp 1777 root root 30d # 清理/var/tmp下30天前的目录和文件
# Exclude namespace mountpoints created with PrivateTmp=yes
# 以下为排出清理的文件
x /tmp/systemd-private-%b-*
X /tmp/systemd-private-%b-*/tmp
x /var/tmp/systemd-private-%b-*
X /var/tmp/systemd-private-%b-*/tmp
原因找到了,系统清理缓存导致,故要么限制系统清理缓存策略文件删除时找不到路径,要么将临时文件上传路径变更到其他路径即可!
异常处理 修改清理策略
不推荐!多台服务器均需修改,而且会遗留很多垃圾文件!
简单暴力,直接修改系统清理策略,在文件末尾添加排出此文件夹:
x /tmp/tomcat.*
启动脚本指定
不推荐!启动命令不方便维护,如果使用自动化部署可以考虑!
DIR=/home/Genterator
FILETMPDIR=${DIR}/FILETMPDIR
nohup java -Xms2048m -Xmx2048m -jar genterator.1.0.0-1.jar --spring.profiles.active=test --server.port=9820 -java.tmp.dir=$FILETMPDIR 2>1&
配置文件指定
推荐!
在properties或者yml中指定:spring.servlet.multipart.location,如下:
spring.servlet.multipart.max-file-size = 20MB
spring.servlet.multipart.max-request-size=100MB
spring.servlet.multipart.location=/home/eccore/tmp
经测试,Linux是可以的文件删除时找不到路径,将缓存文件放入指定路径,但Windows作为开发环境存在异常(可能是我的环境导致,未验证):
[2023-01-31 14:15:43.309] [traceid:e4cdabdc06fb1d5c] [spanId:e4cdabdc06fb1d5c] [http-nio-8084-exec-1] [ERROR] [cn.yto.exceptions.ExceptionCatch:261] -- >>> url:/webApi/finance/ordinaryBill/autoReconciliation, case:Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [C:\Users\yto\AppData\Local\Temp\tomcat.6215628767972368797.8084\work\Tomcat\localhost\webApi\home\eccore\tmp] is not valid
org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [C:\Users\yto\AppData\Local\Temp\tomcat.6215628767972368797.8084\work\Tomcat\localhost\webApi\home\eccore\tmp] is not valid
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.handleParseFailure(StandardMultipartHttpServletRequest.java:123)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:114)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:87)
at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:87)
at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1175)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1010)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at brave.servlet.TracingFilter.doFilter(TracingFilter.java:65)
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.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
…………
Spring注解指定
强烈推荐!
通过SpringBoot的注解@Configuration指定配置类,将对应Bean(MultipartConfigElement)对象注入容器中,替换原来的Bean, 新注入的Bean中指定缓存存放路径!
package cn.yto.steward.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.MultipartConfigElement;
import java.io.File;
/**
* 文件上传配置
*
* @author YTO
* @date 2023年01月31日 13:43
*/
@Slf4j
@Configuration
public class MultipartConfig {
/**
* 文件上传临时路径
*/
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
String location = System.getProperty("user.home") + File.separator + "tmp";
log.info("文件上传临时路径:{}", location);
File tmpFile = new File(location);
if (!tmpFile.exists()) {
boolean mkdirs = tmpFile.mkdirs();
log.info("创建文件上传临时路径:{}, 创建结果:{}", location, mkdirs);
}
factory.setLocation(location);
return factory.createMultipartConfig();
}
}
版权声明
本文仅代表作者观点。
本文系作者授权发表,未经许可,不得转载。
发表评论