关键点在于,多次复用模板流,InputStream只能读取一次,先copy到ByteArrayOutputStream,
    获取byte数组,写到ByteArrayInputStream中,之后每次循环生成一个excel后对stream进行reset,
    这样就可以实现模板流复用,另外excel生成写入到ZipOutputStream后也可以reset复用。

    1. private ExportResultDTO exportZip(Map<String, List<ExcelData>> outMap) {
    2. try (InputStream templateStream = awss3Util.getTemplateAsInputStream(TEMPLATE_NAME);
    3. ByteArrayOutputStream templateStreamOut = new ByteArrayOutputStream();
    4. ByteArrayOutputStream excelOut = new ByteArrayOutputStream();
    5. ByteArrayOutputStream zipOut = new ByteArrayOutputStream();
    6. ZipOutputStream zipOutputStream = new ZipOutputStream(zipOut)) {
    7. IOUtils.copy(templateStream, templateStreamOut);
    8. byte[] bytes = templateStreamOut.toByteArray();
    9. try (ByteArrayInputStream templateByteInputStream = new ByteArrayInputStream(bytes)) {
    10. for (Map.Entry<String, List<ExcelData>> entry : outMap.entrySet()) {
    11. String excelName = entry.getKey();
    12. List<ExcelData> dataList = entry.getValue();
    13. writerStreamByTemplate(excelOut, templateByteInputStream, dataList);
    14. zipOutputStream.putNextEntry(new ZipEntry(excelName));
    15. zipOutputStream.write(excelOut.toByteArray());
    16. templateByteInputStream.reset();
    17. excelOut.reset();
    18. }
    19. }
    20. templateStream.close();
    21. templateStreamOut.close();
    22. excelOut.close();
    23. zipOutputStream.flush();
    24. zipOutputStream.close();
    25. String key = redisUtil.getIncrementKey();
    26. awss3Util.putBytesToDefBucket(key, zipOut.toByteArray());
    27. zipOut.close();
    28. return ExportResultDTO.builder()
    29. .s3ObjectKey(key)
    30. .s3ObjectBucket(AWSS3Util.AWS_S3_BUCKET_DEFAULT)
    31. .contentType("application/zip")
    32. .filename("excel.zip")
    33. .build();
    34. } catch (Exception e) {
    35. log.error(e.getMessage(), e);
    36. throw new RuntimeException("Export excel failed.", e);
    37. }
    38. }
    39. private void writerStreamByTemplate(OutputStream outputStream, InputStream templateStream, List<LGGIOSSManifest2021DTO> dataList) {
    40. ExcelWriter excelWriter = EasyExcel.write(outputStream)
    41. .withTemplate(templateStream)
    42. .build();
    43. WriteSheet writeSheet = EasyExcel.writerSheet().build();
    44. excelWriter.fill(dataList, writeSheet);
    45. excelWriter.finish();
    46. }