报错记录SpringBoot中MultipartFile上传报/tmp/tomcat.***.tmp (No such file or directory)
Posted DCTANT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了报错记录SpringBoot中MultipartFile上传报/tmp/tomcat.***.tmp (No such file or directory)相关的知识,希望对你有一定的参考价值。
前言
我这个接口的需求大概是用户上传一个Excel文件到后端,后端解析这个Excel,并做一系列很耗时的操作。由于这个接口很耗时,因此做成了异步处理的方式,将处理完成的信息通过消息中心告诉用户,并不是立即接口返回。然而这个接口在我本地调试的时候都是好的,上线后就报错了。报错的内容大概是:
/tmp/tomcat.**************.tmp (No such file or directory)
解决过程
很明显是文件找不到,我就去/tmp目录下找,还真的没找到这个文件,我还以为是/tmp目录下的文件会被Linux自动删除导致的报错,结果并不是这样,我在application.yaml中增加上传路径设置,改成了非/tmp目录,结果还是报错!
修改multipart file默认上传临时文件路径的方式:
spring:
servlet:
multipart:
max-file-size: 1024MB
max-request-size: 1024MB
enabled: true
location: /home/test
其中的spring.servlet.multipart.location就是用来设置Tomcat上传临时文件默认路径的,改完后就会上传到这个路径下
我心想应该是解决了,结果还是报错!!报的是/home/test/upload.**************.tmp (No such file or directory)。这下我是清楚了,路径确实是改了,但是还是找不到!进入文件夹后看了一下,确实没有临时文件生成!也就是说这个问题不是因为Linux自动清除/tmp目录的文件导致的,还另有原因。
感谢这篇博客帮我找到了真实原因:
异步处理MultipartFile -- No such file or directory - 青衫执卷 - 博客园
问题解决
这个问题是异步处理导致的,即Tomcat在执行完主线程后就会把这个临时文件删除,导致后面异步线程中Excel解析的时候文件已经找不到了。解决的唯一方法就是把这个文件另存为,然后处理完了手动删除。相当于Tomcat保存一个tmp文件,我再保存一个临时文件,Tomcat在这个主线程执行完了把这个tmp文件删了就删了,而我另存为的临时文件在异步线程Excel解析完了再删除就行了,互相不冲突,然后这个bug就被我解决了。
具体代码
@PostMapping("/excelUpload")
public DataVo excelUpload(HttpServletRequest request)
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("file");
String tmpDir = System.getProperty("java.io.tmpdir");
if (!tmpDir.endsWith("/"))
tmpDir = tmpDir + "/";
String tmpFileOutPath = tmpDir + UUID.randomUUID().toString() + ".tmp";
File tmpFile = new File(tmpFileOutPath);
int byteSize = 8192;
byte[] bytes = new byte[byteSize];
try
InputStream inputStream = file.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
while (true)
int readSize = inputStream.read(bytes);
if (readSize == byteSize)
// bytes是全的
fileOutputStream.write(bytes);
else
// bytes不是全的,到文件末尾了,不足8192字节了
if (readSize == -1)
// INFO: DCTANT: 2022/2/10 如果已经是全部的,就不需要再写入了
else
byte[] tmpByte = new byte[readSize];
for (int i = 0; i < readSize; i++)
tmpByte[i] = bytes[i];
fileOutputStream.write(tmpByte);
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
break;
catch (Exception e)
e.printStackTrace();
// 为了方便理解,直接new Thread了
new Thread(() ->
try
// 这里一段是Excel解析和执行大量业务逻辑的地方,这里就不放出了
// 执行完业务逻辑后删除这个临时文件
tmpFile.delete();
catch (Exception e)
e.printStackTrace();
).start();
// return什么的我省去了,大家自己写吧
主要是这个multipartFile的处理比较麻烦,如果有Hutool可以直接输出,我这边由于没用到,因此还得自己去撸这个文件导出方法,反正这个问题就通过这个方式解决了,没再报文件找不到。
=========================================================
2022年7月27日更新:
multipartFile中的输入流输出到文件其实非常非常简单,完全不需要之前说的这么复杂,multipartFile自带一个方法transferTo,入参是一个File类型目标文件,也就是说直接new File(目标路径);然后multipartFile.transferTo(file)即可!
File localFile = new File(savePath + multipartFile.getOriginalFilename());
try
multipartFile.transferTo(localFile);
catch (IOException e)
e.printStackTrace();
其中savePath需要自己赋值
以上是关于报错记录SpringBoot中MultipartFile上传报/tmp/tomcat.***.tmp (No such file or directory)的主要内容,如果未能解决你的问题,请参考以下文章
报错记录SpringBoot中MultipartFile上传报/tmp/tomcat.***.tmp (No such file or directory)
报错记录SpringBoot中MultipartFile上传报/tmp/tomcat.***.tmp (No such file or directory)
记录springboot项目的maven的pom.xml文件第一行报错 Unknown Error
springMVC:为MultipartFilte配置了上传文件解析器,报错或不能使用
记录:springboot使用resultType报错java.lang.NullPointerException: null...亲测有效