1、使用模版格式设置excel文件,数据对象使用参数化
2、读取模版文件流,写入准备好的数据集合,支持多个sheet一次写入
2、支持多文件打包下载和单文件下载,下面是示例代码
@Override
public void exportBatch(List<Long> idsList, HttpServletResponse response) {
// 判断是否多条 多条 进行压缩下载 单挑直接下载
if (idsList.isEmpty()) {
throw new ParamValidateException(ValidatorExceptionEnum.MISSING_PARAMETER_EXCEPTION, "ids参数不能空");
}
//excel数据源查询
List<InvoiceExport> invoiceExports = baseMapper.selectExport(idsList);
if (CollectionUtil.isEmpty(invoiceExports)) {
throw new FileException(FILE_NOT_FOUND, "未查询到开票业务数据");
}
Long templateId = ConfigContext.me().getConfigValue(InvoiceConstant.INVOICE_EXPORTBATCH_KEY, Long.class);
SysFileInfoResponse sysFileInfo = fileInfoApi.getFileInfoWithoutContent(templateId);
if (sysFileInfo == null) {
throw new FileException(NOT_EXISTED);
}
byte[] fileBytes = fileApi.getFileBytes(FileConfigExpander.getDefaultBucket(), sysFileInfo.getFileObjectName());
if (fileBytes.length < 1) {
throw new FileException(FILE_STREAM_ERROR, "获取文件失败,请检查模板是否存在");
}
if (invoiceExports.size() < 2 ) {
try (InputStream is = new ByteArrayInputStream(fileBytes)) {
String fileName = FileUtils.genFileNameByTime("开票单", ".xlsx");
String downfileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
// 1. 设置响应头,告诉浏览器这是一个文件下载
// 1.1 设置 Content-Type 为 Excel 文件类型
response.setContentType("application/vnd.ms-excel");
// 1.2 设置字符编码
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + downfileName);
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
.withTemplate(is).excelType(ExcelTypeEnum.XLSX).build()) {
WriteSheet writeSheet1 = EasyExcel.writerSheet("1-发票信息").build();
WriteSheet writeSheet2 = EasyExcel.writerSheet("2-发票明细信息").build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(invoiceExports.get(0), fillConfig, writeSheet1);
excelWriter.fill(invoiceExports.get(0).getDetails(), fillConfig, writeSheet2);
}
} catch (Exception e) {
throw new FileException(DOWNLOAD_FILE_ERROR, "请重试");
}
} else {
// 则打压缩包
// 多条数据,需要生成多个Excel文件并压缩下载
String zipFileName = FileUtils.genFileNameByTime("开票单批量", ".zip");
String downZipFileName = null;
try {
downZipFileName = URLEncoder.encode(zipFileName, "UTF-8").replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
throw new FileException(DOWNLOAD_FILE_ERROR, "下载文件名错误");
}
response.setContentType("application/zip");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + downZipFileName);
// 创建临时目录存储Excel文件
Path tempDir = null;
try {
tempDir = Files.createTempDirectory("invoice_export_");
List<File> tempFiles = new ArrayList<>();
// 生成每个Excel文件
for (int i = 0; i < invoiceExports.size(); i++) {
InvoiceExport exportData = invoiceExports.get(i);
String fileName = FileUtils.genFileNameByTime("开票单_" + (i + 1), ".xlsx");
Path tempFile = tempDir.resolve(fileName);
File outPut = tempFile.toFile();
try (InputStream is = new ByteArrayInputStream(fileBytes);
ExcelWriter excelWriter = EasyExcel.write(outPut)
.withTemplate(is).excelType(ExcelTypeEnum.XLSX).build()) {
WriteSheet writeSheet1 = EasyExcel.writerSheet("1-发票信息").build();
WriteSheet writeSheet2 = EasyExcel.writerSheet("2-发票明细信息").build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(exportData, fillConfig, writeSheet1);
excelWriter.fill(exportData.getDetails(), fillConfig, writeSheet2);
tempFiles.add(outPut);
}
}
// 创建ZIP输出流并压缩所有文件
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
byte[] buffer = new byte[1024];
for (File file : tempFiles) {
FileInputStream fis = new FileInputStream(file);
zipOut.putNextEntry(new ZipEntry(file.getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zipOut.write(buffer, 0, length);
}
zipOut.closeEntry();
fis.close();
}
zipOut.finish();
}
} catch (Exception e) {
throw new FileException(DOWNLOAD_FILE_ERROR, "批量导出失败,请重试");
} finally {
// 删除临时文件和目录
if (tempDir != null) {
try {
Files.walk(tempDir)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
} catch (IOException e) {
// 记录日志,但不中断主流程
log.warn("Failed to delete temporary files: {}", e.getMessage());
}
}
}
}
}
发表评论