EasyExcel多线程导出并实现Zip压缩

前言:之前实现的需求由于导出时需要的时间过于长,需要优化采用多线程的方式进行导出

更改之后的代码:

首先创建excel的临时文件,并写入。然后创建线程池,调用zipArchiveOutputStream来写入图片和excel

java 复制代码
@PostMapping("/export3")
    public void exportZip(HttpServletResponse response,
                       @RequestParam(value = "startTime",required = false)String startTime,
                       @RequestParam(value = "endTime",required = false)String endTime,
                       @RequestParam(value = "deviceName",required = false)String deviceName) throws IOException {
        List<CutterImageVO> cutterImageVOList = cutterImageService.getCutterImageList(startTime,endTime,deviceName);
        long start = System.currentTimeMillis();
        String zipFileName = "豁口图片数据";
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFileName + ".zip", "UTF-8"));

        //创建excel临时文件
        final File tempFile = File.createTempFile("tempExcel", ".xls");
        EasyExcel.write(tempFile.getCanonicalPath(),CutterImageVO.class)
                .excelType(ExcelTypeEnum.XLS)
                .registerWriteHandler(new ExcelHyperlinkHandler(1, new int[]{7}))
                .sheet("豁口图片数据")
                .doWrite(cutterImageVOList);
        logger.info("临时文件所在的本地路径:" + tempFile.getCanonicalPath());


        ExecutorService executor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20), new MyRejectedExecutionHandler());
        ParallelScatterZipCreator parallelScatterZipCreator = new ParallelScatterZipCreator(executor);
        OutputStream outputStream = response.getOutputStream();
        ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(outputStream);
        zipArchiveOutputStream.setEncoding("UTF-8");

        try {
            for (int i = 0; i <= cutterImageVOList.size(); i++) {
                int finalI = i;
                String fileName = null;
                if (finalI == cutterImageVOList.size()) {
                    fileName = "豁口图片数据.xls";
                } else {
                    fileName = cutterImageVOList.get(i).getImageUrl();
                }
                String finalFileName = fileName;
                final InputStreamSupplier inputStreamSupplier = () -> {
                    try {
                        InputStream inputStream = null;
                        if (finalI == cutterImageVOList.size()) {
                            inputStream = new FileInputStream(tempFile.getCanonicalPath());
                        } else {
                            inputStream = minioUtil.getDownloadInputStream(finalFileName);
                        }
                        return inputStream;
                    } catch (Exception e) {
                        e.printStackTrace();
                        return new NullInputStream(0);
                    }
                };
                ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(fileName);
                zipArchiveEntry.setMethod(ZipArchiveEntry.DEFLATED);
                zipArchiveEntry.setUnixMode(UnixStat.FILE_FLAG | 436);
                parallelScatterZipCreator.addArchiveEntry(zipArchiveEntry, inputStreamSupplier);
            }
            parallelScatterZipCreator.writeTo(zipArchiveOutputStream);
        }catch(Exception e){
            log.error("文件流读取失败",e);
            e.printStackTrace();
        }finally {
            IOUtils.closeQuietly(zipArchiveOutputStream);
            IOUtils.closeQuietly(outputStream);
        }
        //程序退出时删除临时文件
        tempFile.deleteOnExit();
        long end = System.currentTimeMillis();
        log.info("耗时:"+(end-start));
    }

Minio工具类

java 复制代码
public InputStream getDownloadInputStream(String fileName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
       InputStream is = client.getObject(GetObjectArgs.builder()
               .bucket(minioConfig.getBucketName())
               .object(fileName)
               .build());
       return is;
    }
相关推荐
dtq042416 分钟前
C语言-结构体详解
c语言·开发语言·学习
梅雅达编程笔记28 分钟前
编程启蒙|Scratch 转 Python 系列第9天:字典/哈希表积木双向对照(AI大模型参数配置表实战)
开发语言·人工智能·python·numpy·pandas
持力行29 分钟前
C++与Java变量声明、定义及内存分配的核心区别
java·开发语言·c++
jinyishu_2 小时前
C++ 继承全解:从基础到高级特性
开发语言·c++
接着奏乐接着舞2 小时前
大模型开发 agent 知识库
java
xuhaoyu_cpp_java3 小时前
SpringBoot学习(四)
java·经验分享·spring boot·笔记·学习
plainGeekDev3 小时前
kapt 替换为 KSP
android·java·kotlin
蜡台3 小时前
通过Gradle脚本声明更改Java变量
android·java·开发语言·python·kotlin·gradle·groovy
小喻同学i4 小时前
std::thread函数参数传递
开发语言·c++
程序员天天困4 小时前
后端视角看 EventBus:发布订阅总线的原理、场景与用法
java·后端