springboot 多线程使用MultipartFile读取excel文件内容报错问题

简介: springboot 多线程使用MultipartFile读取excel文件内容报错问题


springboot 多线程使用MultipartFile读取excel文件内容报错问题

springboot项目开启多线程

image.png

image.png

启动类加注解开启 @EnableAsync,实现类方法加注解 @Async

前端页面

image.png

报错信息

主线线程名称:http-nio-8051-exec-6
支线线程名称:threadPoolTaskExecutor-1
java.io.FileNotFoundException: C:\Users\dongao\AppData\Local\Temp\tomcat.1255209411477782290.8051\work\Tomcat\localhost\ROOT\upload_7d7b99e5_38da_4a03_93e0_bff20cb48022_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 org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.getInputStream(StandardMultipartHttpServletRequest.java:250)
  at com.dongao.project.utils.UploadUtil.readExcel(UploadUtil.java:156)
  at com.dongao.project.utils.UploadUtil.readExcelToMap(UploadUtil.java:98)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl.importData(ImportBatchServiceImpl.java:161)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl$$FastClassBySpringCGLIB$$440ed2f6.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
  at com.dongao.support.cat.CatUtils.proceed(CatUtils.java:18)
  at com.dongao.support.cat.CatSpringAop.getObject(CatSpringAop.java:26)
  at com.dongao.support.cat.CatSpringAop.aroundServiceMethod(CatSpringAop.java:22)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
  at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
  at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl$$EnhancerBySpringCGLIB$$a16c4d4e.importData(<generated>)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl$$FastClassBySpringCGLIB$$440ed2f6.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  at java.lang.Thread.run(Thread.java:748)
17:36:46.137 25472 [threadPoolTaskExecutor-1] INFO  com.ruoyi.framework.datasource.DynamicDataSourceContextHolder - [setDataSourceType,26] - 切换到SLAVE数据源
17:36:46.163 25472 [threadPoolTaskExecutor-1] ERROR org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler - [handleUncaughtException,39] - Unexpected exception occurred invoking async method: public void com.dongao.project.importbatch.service.ImportBatchServiceImpl.importData(org.springframework.web.multipart.MultipartFile,java.lang.Long) throws java.lang.Exception
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
  at java.util.ArrayList.rangeCheck(ArrayList.java:653)
  at java.util.ArrayList.get(ArrayList.java:429)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl.importData(ImportBatchServiceImpl.java:178)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl$$FastClassBySpringCGLIB$$440ed2f6.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
  at com.dongao.support.cat.CatUtils.proceed(CatUtils.java:18)
  at com.dongao.support.cat.CatSpringAop.getObject(CatSpringAop.java:26)
  at com.dongao.support.cat.CatSpringAop.aroundServiceMethod(CatSpringAop.java:22)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
  at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
  at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl$$EnhancerBySpringCGLIB$$a16c4d4e.importData(<generated>)
  at com.dongao.project.importbatch.service.ImportBatchServiceImpl$$FastClassBySpringCGLIB$$440ed2f6.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  at java.lang.Thread.run(Thread.java:748)


问题分析

前端页面传过来的文件会存在临时文件夹中,如下

C:\Users\dongao\AppData\Local\Temp\tomcat.1255209411477782290.8051\work\Tomcat\localhost\ROOT\


这个时候如果单线程操作,即正常程序流程解析是不会有问题的;

如果走异步多线程解析文件,主线程已经结束了,临时文件会被清空,这时候再来读取文件就会报错

java.io.FileNotFoundException: C:\Users\dongao\AppData\Local\Temp\tomcat.1255209411477782290.8051\work\Tomcat\localhost\ROOT\upload_7d7b99e5_38da_4a03_93e0_bff20cb48022_00000000.tmp (系统找不到指定的文件。)


问题处理

由于主线程结束,临时文件被清空,导致多线程业务类无法获取到临时文件而报错(系统找不到指定的文件。),此时可以在主线程中转换获取文件流信息

InputStream is = file.getInputStream();

文件流信息存储在内存中,多线程时也可以获取到文件内容,解决问题。


相关文章
|
10天前
|
Java 数据库 数据安全/隐私保护
Java操作Excel文件导入导出【内含有 jxl.jar 】
Java操作Excel文件导入导出【内含有 jxl.jar 】
22 0
|
10天前
|
前端开发 安全 Java
实现Spring Boot中的文件分片上传通常涉及到以下几个步骤和考虑的关键点
实现Spring Boot中的文件分片上传通常涉及到以下几个步骤和考虑的关键点
25 2
|
10天前
|
Java API Spring
集成EasyPoi(一个基于POI的Excel导入导出工具)到Spring Boot项目中
集成EasyPoi(一个基于POI的Excel导入导出工具)到Spring Boot项目中
47 1
|
11天前
|
easyexcel Java API
SpringBoot集成EasyExcel 3.x:高效实现Excel数据的优雅导入与导出
SpringBoot集成EasyExcel 3.x:高效实现Excel数据的优雅导入与导出
35 1
|
12天前
|
API Python
Python库`openpyxl`是一个用于读取和写入Excel 2010 xlsx/xlsm/xltx/xltm文件的库。
【6月更文挑战第19天】`openpyxl`是Python处理xlsx文件的库,支持读写Excel 2010格式。使用`pip install openpyxl`安装。基本操作包括加载文件、读写单元格、操作行和列。例如,加载Excel后,可以读取单元格`A1`的值,或将“Hello, World!”写入`A1`。还可修改单元格内容,如加1后保存到新文件。更多功能,如样式和公式,见官方文档[1]。 [1]: &lt;https://openpyxl.readthedocs.io/en/stable/&gt;
34 1
|
22天前
|
XML Java 测试技术
《手把手教你》系列技巧篇(六十七)-java+ selenium自动化测试 - 读写excel文件 - 中篇(详细教程)
【6月更文挑战第8天】本文介绍了Java中操作Excel的工具,包括POI和JXL。POI支持处理Office 2003及以下的OLE2格式(.xls)和2007以上的OOXML格式(.xlsx)。而JXL只能处理2003版本的Excel文件。文章详细讲解了如何下载和使用JXL库,并给出了一个简单的Java代码示例,展示如何读取2003版Excel文件中的数据。在实际项目中,由于JXL对新版本Excel的支持限制,通常推荐使用POI。
37 5
|
22天前
|
Java 测试技术 Apache
《手把手教你》系列技巧篇(六十八)-java+ selenium自动化测试 - 读写excel文件 - 下篇(详细教程)
【6月更文挑战第9天】本文介绍了如何使用Java处理Excel文件中的不同数据类型,包括日期、数字、布尔值和标签(常规字符串)。文章提供了两个示例,分别使用JXL库和Apache POI库来读取Excel文件。
20 1
|
22天前
|
C#
【C#】C#读写Excel文件
【C#】C#读写Excel文件
21 1
|
23天前
|
Java 测试技术 Apache
《手把手教你》系列技巧篇(六十六)-java+ selenium自动化测试 - 读写excel文件 - 上篇(详细教程)
【6月更文挑战第7天】本文介绍了在Java自动化测试中如何操作Excel数据。文章提到了当测试数据存储在Excel文件时,可以使用Apache的POI库来读写Excel。POI提供了对OLE2(.xls)和OOXML(.xlsx)格式的支持,比JXL库功能更全面。文章还详细讲解了如何下载和添加POI库到项目中,以及准备测试用的Excel文件。最后,给出了一个简单的Java代码示例,演示如何读取Excel文件的内容。
20 1
|
24天前
|
前端开发
react框架对Excel文件进行上传和导出
react框架对Excel文件进行上传和导出