|
SpringBoot使用EasyExcel并行导出多个excel文件并压缩zip下载
SpringBoot的同步导出方式中,服务器会阻塞直到Excel文件生成完毕,这在处理大量数据的导出功能是效率很低,所以我们可以将导出数据拆分后利用CompletableFuture,将导出任务异步化,并行使用easyExcel导出多个excel文件,最后这些文件进一步压缩成ZIP格式以方便下载。
DEMO代码:
- @RestController
- @RequestMapping("/export")
- public class ExportController {
- @Autowired
- private ExcelExportService excelExportService;
- @GetMapping("/zip")
- public ResponseEntity<byte[]> exportToZip() throws Exception {
- List<List<Data>> dataSets = Lists.partition(dataList, 10);
- List<CompletableFuture<String>> futures = new ArrayList<>();
- // 异步导出所有Excel文件
- String outputDir = "path/to/output/dir/";
- for (List<Data> dataSet : dataSets) {
- futures.add(excelExportService.exportDataToExcel(dataSet, outputDir));
- }
- // 等待所有导出任务完成
- CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).get(10, TimeUnit.MINUTES);;
- // 收集Excel文件路径
- List<String> excelFilePaths = futures.stream()
- .map(CompletableFuture::join)
- .collect(Collectors.toList());
- // 压缩文件
- File zipFile = new File("path/to/output.zip");
- try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile))) {
- for (String filePath : excelFilePaths) {
- zipFile(new File(filePath), zipOut, new File(filePath).getName());
- }
- }
- // 返回ZIP文件
- byte[] data = Files.readAllBytes(zipFile.toPath());
- return ResponseEntity.ok()
- .header("Content-Disposition", "attachment; filename="" + zipFile.getName() + """)
- .contentType(MediaType.parseMediaType("application/zip"))
- .body(data);
- }
- // 将文件添加到ZIP输出流中
- private void zipFile(File file, ZipOutputStream zipOut, String entryName) throws IOException {
- try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
- ZipEntry zipEntry = new ZipEntry(entryName);
- zipOut.putNextEntry(zipEntry);
- byte[] bytesIn = new byte[4096];
- int read;
- while ((read = bis.read(bytesIn)) != -1) {
- zipOut.write(bytesIn, 0, read);
- }
- zipOut.closeEntry();
- }
- }
- }
复制代码 异步并行生成excel文件,利用EasyExcel库来简化Excel的生成过程:
- @Service
- public class ExcelExportService {
- private static final String TEMPLATE_PATH = "path/to/template.xlsx";
- @Autowired
- private TaskExecutor taskExecutor;
- public CompletableFuture<Void> exportDataToExcel(List<Data> dataList, String outputDir) {
- Path temproaryFilePath = Files.createTempFile(outputDir, "excelFilePre",".xlsx");
- return CompletableFuture.runAsync(() -> {
- try (OutputStream outputStream = new FileOutputStream(temproaryFilePath )) {
- EasyExcel.write(outputStream, Data.class)
- .withTemplate(TEMPLATE_PATH)
- .sheet()
- .doFill(dataList)
- .finish();
- return temproaryFilePath.toString();
- } catch (IOException e) {
- throw new RuntimeException("Failed to export Excel file", e);
- }
- }, taskExecutor);
- }
- }
复制代码
|
|