当前位置: 首页 > ops >正文

Java后台生成多个Excel并用Zip打包下载

下面是一个完整的实现方案,可以生成多个Excel文件,将它们放入不同的目录结构中,然后打包成ZIP文件供用户下载。


1. 添加必要的依赖

首先确保你的项目中包含以下依赖(Maven示例):

<!-- Apache POI for Excel -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version>
</dependency><!-- Zip工具 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId><version>1.21</version>
</dependency>

2. 实现代码

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;public class ExcelZipExporter {public void exportMultipleExcelsAsZip(HttpServletResponse response) throws IOException {// 设置响应头response.setContentType("application/zip");response.setHeader("Content-Disposition", "attachment; filename=\"reports.zip\"");// 创建Excel文件集合,key为文件路径,value为工作簿Map<String, Workbook> excelFiles = new HashMap<>();// 生成第一个Excel - 放在根目录Workbook workbook1 = generateExcel("销售数据", new String[]{"产品", "数量", "金额"}, new Object[][]{{"产品A", 100, 5000},{"产品B", 150, 7500},{"产品C", 200, 10000}});excelFiles.put("sales_report.xlsx", workbook1);// 生成第二个Excel - 放在monthly目录Workbook workbook2 = generateExcel("月度统计", new String[]{"月份", "收入", "支出"}, new Object[][]{{"一月", 50000, 30000},{"二月", 55000, 32000},{"三月", 60000, 35000}});excelFiles.put("monthly/financial_report.xlsx", workbook2);// 生成第三个Excel - 放在yearly目录Workbook workbook3 = generateExcel("年度汇总", new String[]{"年份", "总收入", "总利润"}, new Object[][]{{"2020", 500000, 150000},{"2021", 550000, 180000},{"2022", 600000, 200000}});excelFiles.put("yearly/summary_report.xlsx", workbook3);// 将Excel文件打包成ZIP并输出到响应流try (OutputStream out = response.getOutputStream();ZipArchiveOutputStream zos = new ZipArchiveOutputStream(out)) {for (Map.Entry<String, Workbook> entry : excelFiles.entrySet()) {// 创建ZIP条目ZipArchiveEntry zipEntry = new ZipArchiveEntry(entry.getKey());zos.putArchiveEntry(zipEntry);// 将Excel工作簿写入ZIP条目ByteArrayOutputStream baos = new ByteArrayOutputStream();entry.getValue().write(baos);zos.write(baos.toByteArray());// 关闭当前条目zos.closeArchiveEntry();// 关闭工作簿entry.getValue().close();}// 完成ZIP文件zos.finish();}}/*** 生成Excel工作簿* @param sheetName 工作表名称* @param headers 表头* @param data 数据* @return 生成的Workbook对象*/private Workbook generateExcel(String sheetName, String[] headers, Object[][] data) {Workbook workbook = new XSSFWorkbook();Sheet sheet = workbook.createSheet(sheetName);// 创建表头行Row headerRow = sheet.createRow(0);for (int i = 0; i < headers.length; i++) {Cell cell = headerRow.createCell(i);cell.setCellValue(headers[i]);// 设置表头样式CellStyle headerStyle = workbook.createCellStyle();Font font = workbook.createFont();font.setBold(true);headerStyle.setFont(font);cell.setCellStyle(headerStyle);}// 填充数据for (int i = 0; i < data.length; i++) {Row row = sheet.createRow(i + 1);for (int j = 0; j < data[i].length; j++) {Object value = data[i][j];Cell cell = row.createCell(j);if (value instanceof String) {cell.setCellValue((String) value);} else if (value instanceof Number) {cell.setCellValue(((Number) value).doubleValue());}}}// 自动调整列宽for (int i = 0; i < headers.length; i++) {sheet.autoSizeColumn(i);}return workbook;}
}

3. 控制器调用示例

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@RestController
@RequestMapping("/api/reports")
public class ReportController {private final ExcelZipExporter excelZipExporter;public ReportController(ExcelZipExporter excelZipExporter) {this.excelZipExporter = excelZipExporter;}@GetMapping("/download")public void downloadExcelReports(HttpServletResponse response) throws IOException {excelZipExporter.exportMultipleExcelsAsZip(response);}
}

4. 功能说明

  1. 生成多个Excel文件:代码中可以创建任意数量的Excel文件,每个文件可以有不同的内容和结构。

  2. 目录结构:通过在文件名中包含路径(如"monthly/financial_report.xlsx"),可以在ZIP包中创建目录结构。

  3. 动态生成:所有Excel文件都是在内存中动态生成的,不需要临时文件。

  4. 直接下载:生成的ZIP文件直接通过HTTP响应流发送给客户端,实现下载功能。

5. 优化建议

  1. 大文件处理:如果Excel文件很大,可以考虑使用SXSSFWorkbook替代XSSFWorkbook以减少内存消耗。

  2. 错误处理:添加适当的错误处理和资源清理代码。

  3. 进度反馈:对于非常大的文件集合,可以考虑实现进度反馈机制。

  4. 压缩级别:可以通过zos.setLevel(Deflater.BEST_COMPRESSION)设置压缩级别。

这个实现方案可以灵活地生成多个Excel文件并按照需要的目录结构打包下载,适用于各种报表导出场景。

http://www.xdnf.cn/news/17906.html

相关文章:

  • 《Python学习之字典(一):基础操作与核心用法》
  • 基于 EC 数据与大模型技术实现天气预报:从数据到上线的全栈方法
  • 学习嵌入式第三十天
  • C++进阶:IO流
  • 【Vibe Coding 工程之 StockAnalyzerPro 记录】- EP3.Phase 2股票列表管理功能
  • JCTools 无锁并发队列基础:ConcurrentCircularArrayQueue
  • TDengine IDMP 高级功能(4. 元素引用)
  • C# 反射和特性(关于应用特性的更多内容)
  • 解锁JavaScript性能优化:从理论到实战
  • C#WPF实战出真汁09--【消费开单】--选择菜品
  • 一次性能排查引发的Spring MVC深度思考
  • Element Plus 中 el-input 限制为数值输入的方法
  • Docker自定义镜像
  • 自动驾驶中的传感器技术24.1——Camera(16)
  • 算法训练营day53 图论④ 110.字符串接龙、105.有向图的完全可达性、106.岛屿的周长
  • Conda创建py3.10环境(股票),并且安装程序包的命令
  • 元宇宙教育:打破时空限制的学习革命
  • 汽车大灯ABD算法介绍
  • SpringAI中的模块化链式Advisor调用(源码学习)
  • B3865 [GESP202309 二级] 小杨的 X 字矩阵(举一反三)
  • Linux 多线程:线程回收策略 线程间通信(互斥锁详解)
  • linux下程序运行一段时间无端崩溃/被杀死,或者内存占用一直增大。linux的坑
  • Docker in Test:用一次性的真实环境,终结“测试永远跑不通”魔咒
  • 集成运算放大器(反向比例,同相比例)
  • C++实战
  • 静态库和动态库
  • 【leetcode】5 最长回文子串 动态规划法
  • Protues使用说明及Protues与Keil联合仿真实现点亮小灯和流水灯
  • 【Docker项目实战】使用Docker部署Notepad轻量级记事本
  • 【基础-判断】HarmonyOS提供了基础的应用加固安全能力,包括混淆、加密和代码签名能力