关键点在于,多次复用模板流,InputStream只能读取一次,先copy到ByteArrayOutputStream,
获取byte数组,写到ByteArrayInputStream中,之后每次循环生成一个excel后对stream进行reset,
这样就可以实现模板流复用,另外excel生成写入到ZipOutputStream后也可以reset复用。
private ExportResultDTO exportZip(Map<String, List<ExcelData>> outMap) {try (InputStream templateStream = awss3Util.getTemplateAsInputStream(TEMPLATE_NAME);ByteArrayOutputStream templateStreamOut = new ByteArrayOutputStream();ByteArrayOutputStream excelOut = new ByteArrayOutputStream();ByteArrayOutputStream zipOut = new ByteArrayOutputStream();ZipOutputStream zipOutputStream = new ZipOutputStream(zipOut)) {IOUtils.copy(templateStream, templateStreamOut);byte[] bytes = templateStreamOut.toByteArray();try (ByteArrayInputStream templateByteInputStream = new ByteArrayInputStream(bytes)) {for (Map.Entry<String, List<ExcelData>> entry : outMap.entrySet()) {String excelName = entry.getKey();List<ExcelData> dataList = entry.getValue();writerStreamByTemplate(excelOut, templateByteInputStream, dataList);zipOutputStream.putNextEntry(new ZipEntry(excelName));zipOutputStream.write(excelOut.toByteArray());templateByteInputStream.reset();excelOut.reset();}}templateStream.close();templateStreamOut.close();excelOut.close();zipOutputStream.flush();zipOutputStream.close();String key = redisUtil.getIncrementKey();awss3Util.putBytesToDefBucket(key, zipOut.toByteArray());zipOut.close();return ExportResultDTO.builder().s3ObjectKey(key).s3ObjectBucket(AWSS3Util.AWS_S3_BUCKET_DEFAULT).contentType("application/zip").filename("excel.zip").build();} catch (Exception e) {log.error(e.getMessage(), e);throw new RuntimeException("Export excel failed.", e);}}private void writerStreamByTemplate(OutputStream outputStream, InputStream templateStream, List<LGGIOSSManifest2021DTO> dataList) {ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(templateStream).build();WriteSheet writeSheet = EasyExcel.writerSheet().build();excelWriter.fill(dataList, writeSheet);excelWriter.finish();}
