alibaba / easyexcel

快速、简洁、解决大文件内存溢出的java处理Excel工具
https://easyexcel.opensource.alibaba.com
Apache License 2.0
32.09k stars 7.5k forks source link

导入excel偶现数组越界 #3928

Closed chuwenyi-cloud closed 1 month ago

chuwenyi-cloud commented 1 month ago

代码如下 ExcelDomainListener excelDomainListener = new ExcelDomainListener(); ExcelReaderBuilder readerBuilder = EasyExcel.read(file.getInputStream(), excelDomainListener); List readSheets = readerBuilder.build().excelExecutor().sheetList(); 获取sheetList会出错

有时候上传会报数组越界,在上传一次又可以了,(数据无变化) 1 2

easyexcel 3.0.5版本

gongxuanzhang commented 1 month ago

excel贴一下

chuwenyi-cloud commented 1 month ago

excel贴一下

知识图谱导入模板 (3).xlsx 知识图谱导入模板-11个 (2).xls 第一次导入都有问题,第二次就好了

chuwenyi-cloud commented 1 month ago

excel贴一下

excel贴一下

我看一下好像是第一次读取的时候ExcelReader类的finalize方法被调用了,然后去释放cache和流了

gongxuanzhang commented 1 month ago

我这边执行代码没有问题,我觉得是因为你的 file.getInputStream() 有问题,建议直接使用File参数

chuwenyi-cloud commented 1 month ago

我这边执行代码没有问题,我觉得是因为你的 file.getInputStream() 有问题,建议直接使用File参数

你好,我这边系统第一次启动必定出现,我大概看了一下 List readSheets = readerBuilder.build().excelExecutor().sheetList(); 我debug发现readerBuilder.build()返回的ExcelReader对象被回收了,触发finsh方法导致ByteArrayBackedDataSource 的size字段变成-1了。然后抛出数组越界的错误了 error

gongxuanzhang commented 1 month ago

你的file.getInputStream() 是MultipartFile的inputStream, 不是File的. 当MultipartFile.close的时候(非内存模式),tomcat会直接关闭管道,所以我说是你的file.getInputStream()有问题.且你在描述问题的时候避开了MultipartFile和File的问题, 我的建议是如果文件不大,可以持久化下来用File句柄替代MultipartFile

chuwenyi-cloud commented 1 month ago

MultipartFile

你好,如果是这样那为什么我第二次上传就会成功尼?如果是这样的话那么每次上传都会失败,实际上并没有。一开始我认为没有强引用关联到ExcelReader对象导致被回收了,然后我把 List readSheets = readerBuilder.build().excelExecutor().sheetList(); 改成这 ExcelReader build = readerBuilder.build(); List readSheets =build.excelExecutor().sheetList(); 发现就好了并没有在系统刚启动第一次上传就会被回收了 (ps 之前上传失败都是系统启动后第一次调用后失败,后面均正常了且文件类型读取出来都是xls)

psxjoy commented 1 month ago

I think @gongxuanzhang explanation reasonable. If you still have concerns, please provide a minimal reproducible demo.

我认为 @gongxuanzhang 的解释是合理的。如果还是有疑问的话,麻烦提供最小可复现demo。

chuwenyi-cloud commented 1 month ago

I think @gongxuanzhang explanation reasonable. If you still have concerns, please provide a minimal reproducible demo.

我认为 @gongxuanzhang 的解释是合理的。如果还是有疑问的话,麻烦提供最小可复现demo。 @PostMapping("/domain/upload") public ExcelResult limitImport(@RequestPart @RequestParam("file") MultipartFile file) { //初始化监听器 ExcelDomainListener excelDomainListener = new ExcelDomainListener(); //解析数据 try { ExcelReaderBuilder readerBuilder = EasyExcel.read(file.getInputStream(), excelDomainListener); List readSheets = readerBuilder.build().excelExecutor().sheetList(); } catch (IOException e) { log.error("导入失败; 异常信息:{}", e); } return ExcelResult.errorMsg("导入失败"); } 本地启用项目,使用apifox调用接口第一次就会出现 exasyexcel版本 3.0.5 知识图谱导入模板-单个 (2).xls

psxjoy commented 1 month ago

It seems this line of code is causing the issue.

List readSheets = readerBuilder.build().excelExecutor().sheetList();

I don't have time to investigate the exact cause right now (I’ll continue to follow up). I adjusted your implementation, and the code below seems to work fine.

    @RequestMapping("/domain/upload")
    public String limitImport(@RequestPart @RequestParam("file") MultipartFile file) throws Exception {
        //初始化监听器
        //解析数据
        try {
            ExcelReaderBuilder excelReaderBuilder = EasyExcel.read(file.getInputStream(), new ReadListener() {
                @Override
                public void invoke(Object o, AnalysisContext analysisContext) {
                    System.out.println(JSON.toJSONString(o));
                }
                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                }
            });
            ExcelReader excelReader = excelReaderBuilder.build();
            List readSheets = excelReader.excelExecutor().sheetList();

            System.out.println(JSON.toJSONString(readSheets));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "finfish";
    }
chuwenyi-cloud commented 1 month ago

I don't have time to investigate the exact cause right now (I’ll continue to follow up). I adjusted your implementation, and the code below seems to work fine.

好的,谢谢。当时我debug代码时候发现excelReader被回收了导致触发了这个问题。弄个强应用指向ExcelReader应该就可以了