当前位置:   article > 正文

java.io.FileNotFoundException与java.io.IOException_java 文件上传生成tmp 找不到

java 文件上传生成tmp 找不到

FileNotFoundException

开发背景:系统需添加一个云盘模块,有文件上传功能,同步上传大文件传输速度很慢,用户等待时间过长,采取了异步上传。发现有时存在系统找不到指定的文件,导致上传失败的问题。

发现问题:网络查找发现是springboot文件上传,会创建临时目录保存临时文件,处理完后会清除。

报错信息如下:

  1. java.io.FileNotFoundException: C:\Users\***\work\Catalina\localhost\ROOT\upload_22e2506c_3d38_4755_8ea1_f81b600f8c2e_00000005.tmp (系统找不到指定的文件。)
  2. at java.io.FileInputStream.open0(Native Method)
  3. at java.io.FileInputStream.open(FileInputStream.java:195)
  4. at java.io.FileInputStream.<init>(FileInputStream.java:138)
  5. at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.getInputStream(DiskFileItem.java:194)
  6. at org.apache.catalina.core.ApplicationPart.getInputStream(ApplicationPart.java:100)
  7. at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.getInputStream(StandardMultipartHttpServletRequest.java:296)
  8. at cn.com.teacher.service.impl.MyCloudStorageServiceImpl.saveFile(MyCloudStorageServiceImpl.java:75)
  9. at cn.com.teacher.service.impl.MyCloudStorageServiceImpl.lambda$saveCloudStorageFile$0(MyCloudStorageServiceImpl.java:64)
  10. at java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1626)
  11. at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)
  12. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  13. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  14. at java.lang.Thread.run(Thread.java:748)

之前代码:

  1. CompletableFuture.runAsync(()->{
  2. saveFile(MultipartFile);
  3. },executor);

现在代码:

  1. InputStream inputStream = multipartFile.getInputStream();
  2. CompletableFuture.runAsync(()->{
  3. //传递流
  4. saveFile(inputStream);
  5. },executor);

解决方案:改为传递流

IOException

出现地点:需要把文件上传到OSS上,流关闭,后面需生成文件的md5值,工具类,也需要InputStream,里面也把流关闭,出现了问题。

发现问题:InputStream只能读取一次,如果需要重复读取,需要转换或者存储。

报错信息:java.io.IOException: Stream Closed

解决方案:InputStream不支持重置,但是它的子类ByteArrayInputStream支持

  1. //InputStream代码
  2. public synchronized void mark(int readlimit) {}
  3. public synchronized void reset() throws IOException {
  4. throw new IOException("mark/reset not supported");
  5. }
  6. public boolean markSupported() {
  7. return false;
  8. }
  1. //ByteArrayInputStream代码
  2. protected int mark = 0;
  3. //是否支持重置
  4. public boolean markSupported() {
  5. return true;
  6. }
  7. //定点,下次从哪里重新读取
  8. public void mark(int readAheadLimit) {
  9. mark = pos;
  10. }
  11. //重置到定点位置后,可重新读取
  12. public synchronized void reset() {
  13. pos = mark;
  14. }

把InputStream转换未ByteArrayInputStream,第二次使用前使用重置方法即可

byteArrayInputStream.reset();

下面转换代码取自:InputStream重复使用小技巧_I_am_zz.的博客-CSDN博客_inputstream重复使用

  1. public static ByteArrayInputStream toByteArrayInputStream(InputStream inputStream) throws IOException {
  2. if (inputStream instanceof ByteArrayInputStream) {
  3. return (ByteArrayInputStream) inputStream;
  4. }
  5. try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
  6. BufferedInputStream br = new BufferedInputStream(inputStream);
  7. byte[] b = new byte[1024];
  8. for (int c; (c = br.read(b)) != -1; ) {
  9. bos.write(b, 0, c);
  10. }
  11. // 主动告知回收
  12. b = null;
  13. br.close();
  14. inputStream.close();
  15. return new ByteArrayInputStream(bos.toByteArray());
  16. }
  17. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/976606
推荐阅读
相关标签
  

闽ICP备14008679号