alibaba / easyexcel

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

使用Web导出文件是,大对象无法被回收,导致OOM #3533

Open fatelpc opened 9 months ago

fatelpc commented 9 months ago

问题描述,使用Web导出文件是,大对象无法被回收,导致OOM

快速开始常见问题

异常代码

 public void downloadDebugInfo(
            HttpServletResponse response,
            @RequestParam(name = "taskId") String taskId,
            @RequestParam(name = "versionId") String versionId) throws IOException {
        long startTime = System.currentTimeMillis();
        ExportResult exportResult = diffService.getDebugResult(Long.valueOf(taskId), Long.valueOf(versionId));
        long endTime = System.currentTimeMillis();
        long elapsedTime = endTime - startTime;
        log.info("导出计算运行时间:" + elapsedTime + "ms");
        // 接口测试 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码
        String fileName = URLEncoder.encode(exportResult.getFileName(), "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) {
            if (!CollectionUtils.isEmpty(exportResult.getNoteDebugInfoList())) {
                List<NoteSearchDataExpExcel> noteDebugInfoList = exportResult.getNoteDebugInfoList();
                WriteSheet gsbWriteSheet = EasyExcel.writerSheet(0, "Diff结果").head(NoteSearchDataExpExcel.class).build();
                excelWriter.write(noteDebugInfoList, gsbWriteSheet);
            } else {
                List<NoteFeedDataExpExcel> noteDebugInfoList = exportResult.getNoteFeedDataExpExcelList();
                WriteSheet gsbWriteSheet = EasyExcel.writerSheet(0, "Diff结果").head(NoteFeedDataExpExcel.class).build();
                excelWriter.write(noteDebugInfoList, gsbWriteSheet);
            }
        } catch (Exception e) {
            log.error("scoring export error. ", e);
            throw new DroomException("导出Diff异常");
        } finally {
            exportResult.clear();
            exportResult = null;
            System.gc();
        }
    }

问题描述

使用Web导出文件是,大对象无法被回收,导致OOM, 通过分析代码里面的 List noteDebugInfoList 无法被回收

madull commented 8 months ago

1.试试看直接先写Excel文件再文件下载 2.尝试write完后清空dataList 3.再dataList=null 引用设置null

hausen1012 commented 7 months ago

1.试试看直接先写Excel文件再文件下载 2.尝试write完后清空dataList 3.再dataList=null 引用设置null

请问先写Excel文件再文件下载这个有案例吗?可以断点续传吗?再补充一下,我的导出包含图片,是否可以先写文件?

Codefor4learn commented 5 months ago

请问解决了吗

madull commented 3 months ago

https://blog.csdn.net/qq_38249409/article/details/129127289 可以参考一下这个