由于zip4j用法限制,不能够直接使用流的形式进行转换,加密等操作;需要将excel,以及压缩好的文件放在某个位置后,再读取给response才能返回给浏览器。方法如下:
引入依赖
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
线程池配置
@Configuration
@EnableAsync
public class ExcutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExcutorConfig.class);
@Value("${yml/properties中配置的参数}")
private int corePoolSize;
@Value("同上")
private int maxPoolSize;
@Value("同上")
private int keepAliveSeconds;
@Value("同上")
private int queueCapacity;
@Bean("downLoadExecutor")//调用线程时的线程名字
public Executor asyncExcelServiceExecutor() {
logger.info("...ExecutorConfig...asyncServiceExecutor()...启动[发布任务]线程池...");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
controller前端调用接口
@PostMapping("/exportZip")
@ApiOperation(value = "导出压缩包", notes = "导出压缩包")
public void exportZip(
@RequestBody QueryDto QueryDto, HttpServletResponse response) {
exportService.exportzip(QueryDto, response);
}
压缩加密主业务
@Override
public void exportzip(QueryDto QueryDto, HttpServletResponse response) {
ServletOutputStream outputStream = null;
InputStream inputStream = null;
String path = null;
String now = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.zip;charset=UTF-8");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader(
"Content-Disposition",
"attachment; filename=" + new String((now + ".zip").getBytes("UTF-8"), "ISO8859-1"));
log.info("---response缓冲区大小:" + response.getBufferSize());
response.setBufferSize(60000);
log.info("---response缓冲区调整后:" + response.getBufferSize());
outputStream = response.getOutputStream();
//加闩--两个线程同时执行查询
CountDownLatch latch = new CountDownLatch(2);
exportAsync.queryTable1(latch, 100, QueryDto);
exportAsync.queryTable2(latch, 100, QueryDto);
//等待2个线程执行完毕
latch.await();
log.info("------所有excel打包zip---start------");
net.lingala.zip4j.core.ZipFile zip = null;
net.lingala.zip4j.io.ZipOutputStream zipOutputStream =
new net.lingala.zip4j.io.ZipOutputStream(response.getOutputStream());
//获取上一步骤中存有excel的文件夹
path = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "/";
File file = new File(path);
zip =
new net.lingala.zip4j.core.ZipFile(
path + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".zip");
//设置加密参数
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
zipParameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
zipParameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
zipParameters.setPassword("123456");
zip.addFolder(file, zipParameters);
File fileZip =
new File(
path + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".zip");
//获取zip文件输入流,写入response返回
inputStream = new FileInputStream(fileZip);
int len;
byte[] buf = new byte[1024];
while ((len = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, len);
}
} catch (ZipException e) {
e.getStackTrace();
throw new BizException(ResponseCodeEnum.EXPORT_EXCEL_ZIP_EXCEPTION);
} catch (InterruptedException e) {
e.getStackTrace();
throw new BizException(ResponseCodeEnum.EXPORT_EXCEL_ZIP_EXCEPTION);
} catch (IOException e) {
e.getStackTrace();
throw new BizException(ResponseCodeEnum.EXPORT_EXCEL_ZIP_EXCEPTION);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
throw new BizException(ResponseCodeEnum.EXPORT_EXCEL_ZIP_EXCEPTION);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
throw new BizException(ResponseCodeEnum.EXPORT_EXCEL_ZIP_EXCEPTION);
}
}
}
//返回浏览器后删除暂存的文件夹和文件
deleteDir(path);
}
开启线程查询数据
@Async("downLoadExecutor")
public void excelZdOperation(
CountDownLatch latch, int excelSize, GroupVersionQueryDto versionQueryDto)
throws IOException {
String currentThreadName = Thread.currentThread().getName();
log.info("---线程: 【" + currentThreadName + "】 ---startexcel---");
//封装queryWrapper条件,查询数据
QueryWrapper<Enrity> queryWrapper = new QueryWrapper<>();
queryWrapper
.lambda()
.eq(Enrity::getId, QueryDto.getId())
.eq(Enrity::getIsValid, Constants.VALID_YES)
Integer count = entityMapper.selectCount(queryWrapper);
if (count > 0) {
int totalPage = count % excelSize == 0 ? count / excelSize : count / excelSize + 1;
for (int i = 0; i < totalPage; i++) {
Page<Enrity> page = new Page<>(i + 1, excelSize);
IPage<Enrity> entityIPage =
entityMapper.selectPage(page, QueryWrapper);
List<Enrity> records = entityIPage .getRecords();
List<EnrityExportDto> EnrityDtos = enrityMapping.domain2DtoList(records);
toExcel(
zdOperationDtos,
ZdOperationExportDto.class,
TableNameEnum.TABLE_NAME1.getMsg() + (i + 1));
}
}
latch.countDown();
}
easyExcel生成excel临时文件
private synchronized void toExcel(List data, Class clazz, String excelName) throws IOException {
//创建暂存excel文件的文件夹,以当前日期格式命名
String path = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "/";
File fileAddPath = new File(path);
if (!fileAddPath.exists()) {
fileAddPath.mkdirs();
}
//通过easyExcel生成xlsx文件,并暂存
File excel = new File(path + excelName + ".xlsx");
String sheetName1 = "sheet1";
ExcelWriter writer = EasyExcel.write(excel, clazz).build();
WriteSheet writeSheet = EasyExcel.writerSheet(sheetName1).build();
//导出excel
writer.write(data, writeSheet);
writer.finish();
}
删除临时文件夹数据
private void deleteDir(String dirPath) {
File file = new File(dirPath);
if (file.isFile()) {
file.delete(); // 删除文件
} else {
File[] files = file.listFiles();
if (files == null) {
file.delete(); // 删除空文件夹
} else {
for (File f : files) {
deleteDir(f.getAbsolutePath()); // 迭代删除非空文件夹
}
file.delete();
}
}
}
案例中用到的技术点描述:
1.mybatisPlus
2.easyExcel
3.zip
4.mapstruct
5.线程池异步执行