【踩坑日记】springboot MultipartFile上传,@Async异步执行时报错:java,io.FileNotFoundException

项目场景:

springboot 项目中使用MultipartFile上传文件导入时,文件内容过大会导致页面等待时间较长,所以考虑使用上传文件时用@Async异步处理数据的方式来解决页面等待问题。


问题描述

给处理MultipartFile文件的方法添加@Async注解后,上传文件时出现异常,找不到临时文件

异常如下:

(org. springramework.web.multipart,MultipartFile,java.lang.Integer) throws java.io. IOExcept.onjava,io.FileNotFoundException: /tmp/tomcat,6802674863357158901,1070/work/Tomct/localhost/HHY/upload f5e77369 7db0 4bdd 8cf7 921ddb06e2b8 00000002.trp (No such file or directory)

ream(DiskFileItem.java:194at org.apachetomcat .util.http.fileupload.disk.DiskFileltem.getInputSat org.apache.catalina.core.ApplicationPart.getInputStream(ApplicatioPart.java:100)at org.springframework.web .multipart .support.StandardMultipartHttpSerTetRequestsStandardMultipartFile.getBytes(StandardMultipartHttpServletRequest .jva:245) ......

接口代码:

java 复制代码
  @PostMapping("/importData")
  public Boolean importData(
      HttpServletResponse response,
      @RequestParam("file") MultipartFile file) {
    try {
      formatManagementService.importData(file);
      return true;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return false;
  }

// 异步处理导入的文件内容
  @Async
  public Boolean importData(MultipartFile file)
      throws IOException {
// 文件内容处理逻辑
....

  }

原因分析:

首先:前端传递过来的文件,会存储到临时文件夹中,即上面报错的文件路径位置;但是如果方法是异步执行的时候,主线程结束,临时文件就会被清空,所以会报上面的异常:


解决方案:

所以这里我们如果要通过异步处理,就需要转换成输入流来操作,通过传参的方式将输入流传到异步方法内。在异步方法内使用完毕再释放输入流:

代码如下:

java 复制代码
  @PostMapping("/importData")
  public Boolean importData(
      HttpServletResponse response,
      @RequestParam("file") MultipartFile file) {
    try {
      formatManagementService.importData(file.getInputStream());
      return true;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return false;
  }

// 异步处理导入的文件内容
  @Async
  public Boolean importData(InputStream fileInputStream)
      throws IOException {

          try {
            // 文件内容处理逻辑
            ....
          } catch (Exception e) {
            log.error("导入异常", e);
          }finally{
            if (fileInputStream!=null){
              fileInputStream.close();
            }
          }

  }

总结:

@Async需要注意使用事项,例如像循环依赖调用的影响等问题;

提醒:输入流对象在异步方法使用完后记得关闭流,否则会一直占用内存资源,并且服务器本地的缓存文件也无法更改或删除

相关推荐
ps酷教程5 小时前
Jackson 解决没有无参构造函数的反序列化问题
java
NiceCloud喜云5 小时前
Opus 4.8 的 Effort Control 怎么选:Low 到 Max 五档策略
android·java·大数据·前端·c++·python·spring
_日拱一卒6 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
隔窗听雨眠6 小时前
Nginx网关响应慢排查手记
java·服务器·nginx
智慧物业老杨6 小时前
智慧物业合同周期管理系统:从风险预警到智能交接的全流程数智化落地方案
java·人工智能·python
源码宝7 小时前
MES系统源码:Java8 + SpringBoot2.7 + MySQL8 + Redis,后端源码清爽易扩展
java·后端·源码·springboot·mes系统·源码二开·mes源码
JAVA社区7 小时前
Java高级全套教程(十)—— SpringCloudAlibaba超详细实战详解
java·开发语言·spring cloud·面试·职场和发展
金銀銅鐵7 小时前
[Java] 如何理解 class 文件中方法的 descriptor?
java·后端
云烟成雨TD8 小时前
Spring AI Alibaba 1.x 系列【63】AI Agent 长期记忆
java·人工智能·spring
憧憬成为java架构高手的小白8 小时前
苍穹外卖--day09
java·spring boot·百度