异步处理multipartFile,找不到临时文件,java.io.FileNotFoundException:xxx.tmp (系统找不到指定的文件。)


前言

需求:之前做 multipartFile 文件上传处理时是同步的,现要将同步处理改为异步处理。


提示:以下是本篇文章正文内容,下面案例可供参考

一、问题描述

  • 问题:当同步改为多线程处理或者加上@Async 异步处理时,会报错:java.io.FileNotFoundException 系统找不到指定的文件
java.io.FileNotFoundException: C:\Users\minis\AppData\Local\Temp\tomcat.8973262732558840642.8011\work\Tomcat\localhost\ROOT\upload_8b7dee27_e34d_47e9_b755_cea7d688aa94_00000000.tmp (系统找不到指定的文件。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.getInputStream(DiskFileItem.java:194)
	at org.apache.catalina.core.ApplicationPart.getInputStream(ApplicationPart.java:100)
	at com.alpari.web.service.impl.UserServiceImpl.asyncFile(UserServiceImpl.java:22)
......
  • 代码:异步处理 MultipartFile
@Autowired
private UserService userService;

@PostMapping("/demoUpload")
public String demoUpload(MultipartFile file) {
    // 异步处理 file
    userService.asyncFile(file);
    return "success";
}

// 注意要在启动类上加 @EnableAsync
@Async
@Override
public void asyncFile(MultipartFile file) {
    try {
    	// 这边睡了一会是模拟文件相关操作的时间
        Thread.sleep(200);
        file.getInputStream();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 原因:异步执行,当主线程执行完,临时文件会被清空,而此时异步线程并未执行完

前端传过来的文件会存储到临时文件夹中,当我们的方法是异步执行时(即加上 @Async 注解或者在多线程中执行),主线程结束时,临时文件就会被清空,而异步线程未结束,所以在使用文件时就会报找不到文件错误。

二、解决方案

1.将 MultipartFile 文件转换为流

@PostMapping("/demoUpload")
public String demoUpload(MultipartFile file) {
    // 异步处理 file
    try {
        userService.asyncFileInputStream(file.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "success";
}

@Async
@Override
public void asyncFileInputStream(InputStream inputStream) {
    try {
        Thread.sleep(200);
        System.out.println(inputStream);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
    	// 关闭流
        IOUtils.closeQuietly(inputStream);
    }
}

2.将 MultipartFile 文件转换为字节数组

@PostMapping("/demoUpload")
public String demoUpload(MultipartFile file) {
    // 异步处理 file
    try {
    	// 转换成String是为了方便接收 MultipartFile[],可以转换成 String[]
        String base64Bytes = Base64.getEncoder().encodeToString(file.getBytes());
        userService.asyncFileBase64Bytes(base64Bytes);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "success";
}

@Async
@Override
public void asyncFileBase64Bytes(String base64Bytes) {
    try {
        Thread.sleep(200);
        // 转换为流,使用完毕后关闭,此代码片段省略...
        ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(base64Bytes));
        System.out.println(inputStream);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

总结

爱是理解,爱是等待,爱是包容,爱是不强求。

在这里插入图片描述

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值