springboot 上传文件报错:java.io.IOException: The temporary upload location [/tmp/tomcat.xxx] is not valid

本文介绍了SpringBoot项目中遇到的文件上传异常,即由于/Linux系统的tmpwatch命令删除了Tomcat的临时文件目录导致的问题。解决方案包括重启SpringBoot应用或修改配置以指定新的临时文件目录。作者提醒开发者注意上线项目的预警机制和问题排查。

前言: 

之前上线半个月后的项目,突然发现图片上传的接口有问题,无法上传,提示java.io.IOException: The temporary upload location [/tmp/tomcat.7538204303517105479.8899/work/Tomcat/localhost/main_service] is not valid的异常,经过百度,才知道这个是springboot项目文件上传的一个坑。

正文:

我们先复现下问题:

1.用postman调用图片上传的接口

2. 登录xshell去查看下日志

2019-06-05 11:04:35.904 [http-nio-8899-exec-10] ERROR o.a.c.c.C.[.[.[/main_service].[dispatcherServlet]  Servlet.service() for servlet [dispatcherServlet] in context with path [/main_service] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.7538204303517105479.8899/work/Tomcat/localhost/main_service] is not valid] with root cause
java.io.IOException: The temporary upload location [/tmp/tomcat.7538204303517105479.8899/work/Tomcat/localhost/main_service] is not valid
	at org.apache.catalina.connector.Request.parseParts(Request.java:2821)
	at org.apache.catalina.connector.Request.getParts(Request.java:2754)
	at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1098)
	at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:94)
	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 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)
	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(StandardWrapper
### Spring Boot 文件上传 `Failed to parse multipart servlet request` 错误解决方案 当在Spring Boot应用程序中执行文件上传操作时,如果遇到类似于“Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [...] is not valid”的错误,通常是因为临时存储路径不可用或未正确配置。 以下是详细的分析和解决方法: #### 1. **原因分析** 该错误的根本原因是Tomcat服务器无法找到有效的临时目录来保存上传文件片段。默认情况下,Spring Boot 使用 Tomcat 的内置功能处理多部分请求 (multipart requests),而这些请求的数据会被暂时写入到系统的临时目录下。然而,在某些环境中(例如 Linux 或 Docker 容器),/tmp 目录可能被清理或者不存在足够的权限[^1]。 此外,Windows 用户可能会看到类似的错误消息指出 C:\Users\XXX\AppData\Local\Temp 下的具体子目录无效[^2]。 --- #### 2. **解决办法** ##### 方法一:自定义临时目录 可以通过修改 application.yml 配置文件中的参数指定一个可靠的本地磁盘位置作为新的临时文件夹。例如: ```yaml spring: http: multipart: location: /data/upload_tmp # 设置为具有适当读写权限的位置 ``` 上述代码指定了 `/data/upload_tmp` 路径用于存放中间状态数据。确保此路径存在并且应用进程对该路径拥有必要的访问权限[^3]。 ##### 方法二:调整操作系统级别的环境变量 对于 Unix/Linux 系统而言,可以尝试通过更改 JAVA_OPTS 来重新设定 JVM 启动选项里的 `-Djava.io.tmpdir=/path/to/new/tmp/dir` 参数指向另一个稳定的 temp area 。比如启动命令可改为: ```bash JAVA_OPTS="-Xms512m -Xmx1g -XX:+UseG1GC -Djava.io.tmpdir=/custom/temp" java $JAVA_OPTS -jar your-spring-boot-app.jar ``` 这一步骤能够覆盖掉原本由 OS 提供的标准 tmp 地址设置[^4]。 ##### 方法三:验证 Content-Type 请求头 确认客户端发送 HTTP POST 请求的时候携带了正确的 content-type 值。“multipart/form-data” 是标准形式之一,但是具体实现细节取决于实际使用的库版本以及边界字符串格式化方式是否匹配服务端预期。不恰当的内容类型声明也可能引发解析失败的情况。 --- #### 3. **注意事项** - 如果部署的是容器化的微服务架构,则需特别留意宿主机与内部映射关系之间的协调工作。 - 对于生产环境下运行的应用程序来说,建议始终显式地定义好所有涉及 I/O 操作的相关资源定位符及其安全属性。 --- ### 示例代码展示如何测试文件上传接口 下面给出一段简单的控制器逻辑用来接收单个文件对象并打印基本信息至控制台日志输出流上: ```java import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/upload") public class FileUploadController { @PostMapping(consumes = "multipart/form-data") public String handleFileUpload(@RequestParam("file") MultipartFile file){ if (!file.isEmpty()) { System.out.println("Received file name : "+file.getOriginalFilename()); return "Uploaded successfully!"; }else{ return "No file selected."; } } } ``` 以上例子展示了基本的功能模块构建思路,便于开发者快速搭建原型级的服务端点来进行调试诊断活动。 ---
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心的码字达

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值