EasyPoi + iText 5.x 和EasyPoi +PDFBox 把数据导出成pdf

发布时间:2026/7/21 8:56:26
EasyPoi + iText 5.x 和EasyPoi +PDFBox 把数据导出成pdf EasyPoi 官方开源免费导出 PDF 的核心思路是EasyPoi 生成 Excel再用开源 PDF 库将 Excel 渲染成 PDF 文件。下面分别给出 iText 5.x 和 PDFBox 两种方案的完整实现代码。 方案一iText 5.xEasyPoi 官方推荐这是 EasyPoi 官方文档中明确支持的方案依赖itextpdf和itext-asian两个包。Maven 依赖xml!-- EasyPoi 核心 -- dependency groupIdcn.afterturn/groupId artifactIdeasypoi-base/artifactId version5.3.4/version /dependency dependency groupIdcn.afterturn/groupId artifactIdeasypoi-annotation/artifactId version5.3.4/version /dependency !-- iText 5.x PDF 支持optional 表示可选依赖 -- dependency groupIdcom.itextpdf/groupId artifactIditextpdf/artifactId version5.5.6/version /dependency dependency groupIdcom.itextpdf/groupId artifactIditext-asian/artifactId version5.2.0/version /dependency完整代码EasyPoi 导出 Excel iText 转 PDFjavaimport cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; RestController public class PdfExportController { GetMapping(/export/pdf) public void exportPdf(HttpServletResponse response) throws Exception { // 1. EasyPoi 生成 Excel ListUser userList buildUserList(); ExportParams params new ExportParams(员工信息表, 员工数据); Workbook workbook ExcelExportUtil.exportExcel(params, User.class, userList); // 2. 将 Excel 转换为 PDFiText 5.x 方式 ByteArrayOutputStream baos new ByteArrayOutputStream(); workbook.write(baos); byte[] excelBytes baos.toByteArray(); // 使用 iText 读取 Excel 转换后的 PDF Document document new Document(PageSize.A4); PdfWriter writer PdfWriter.getInstance(document, response.getOutputStream()); // 3. 设置响应头返回 PDF response.setContentType(application/pdf); response.setHeader(Content-Disposition, attachment; filename员工报表.pdf); document.open(); PdfContentByte cb writer.getDirectContent(); // 将 Excel 内容写入 PDFiText 原生方式 PdfReader reader new PdfReader(excelBytes); int totalPages reader.getNumberOfPages(); for (int i 1; i totalPages; i) { document.newPage(); PdfImportedPage page writer.getImportedPage(reader, i); cb.addTemplate(page, 0, 0); } document.close(); reader.close(); } private ListUser buildUserList() { ListUser list new ArrayList(); list.add(new User(张三, 25, 男)); list.add(new User(李四, 22, 女)); list.add(new User(王五, 28, 男)); return list; } Data AllArgsConstructor public static class User { Excel(name 姓名, width 20) private String name; Excel(name 年龄, width 20) private Integer age; Excel(name 性别, width 20) private String sex; } }iText 5.x 方案要点关键点说明中文支持必须引入itext-asian包否则中文字符无法显示字体设置使用BaseFont.createFont(STSong-Light, UniGB-UCS2-H, BaseFont.NOT_EMBEDDED)支持中文协议风险iText 5.x 采用AGPL-3.0协议商业闭源项目需谨慎 方案二PDFBoxEasyPoi 4.4.0 推荐从 EasyPoi 4.4.0 开始官方推荐使用PDFBox替代 iText因为 PDFBox 采用Apache License 2.0对商业使用更友好。Maven 依赖xmldependency groupIdcn.afterturn/groupId artifactIdeasypoi-base/artifactId version4.4.0/version /dependency !-- Apache PDFBox -- dependency groupIdorg.apache.pdfbox/groupId artifactIdpdfbox/artifactId version2.0.29/version /dependency完整代码PDFBox 转换 Excel 为 PDF⚠️ 注意PDFBox 目前没有像 iText 那样直接addTemplate导入 Excel 的功能因此需要将 Excel 内容逐行读取后用 PDFBox 的PDPageContentStream重新绘制表格。javaimport cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.PDType0Font; import org.apache.poi.ss.usermodel.*; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.List; RestController public class PdfBoxExportController { GetMapping(/export/pdfbox) public void exportPdfWithPdfBox(HttpServletResponse response) throws Exception { // 1. EasyPoi 生成 Excel ListUser userList buildUserList(); ExportParams params new ExportParams(员工信息表, 员工数据); Workbook workbook ExcelExportUtil.exportExcel(params, User.class, userList); // 2. 读取 Excel 数据 Sheet sheet workbook.getSheetAt(0); int rowCount sheet.getPhysicalNumberOfRows(); // 3. 使用 PDFBox 创建 PDF PDDocument document new PDDocument(); PDPage page new PDPage(PDRectangle.A4); document.addPage(page); // 加载中文字体需准备 simhei.ttf 或使用系统字体 InputStream fontStream getClass().getResourceAsStream(/fonts/simhei.ttf); PDType0Font font PDType0Font.load(document, fontStream); PDPageContentStream contentStream new PDPageContentStream(document, page); // 设置字体和起始位置 float yPosition 750; float xPosition 50; float rowHeight 20; float colWidth 100; // 遍历 Excel 行绘制表格 for (int i 0; i rowCount; i) { Row row sheet.getRow(i); if (row null) continue; // 绘制行边框 contentStream.setStrokingColor(0); contentStream.setLineWidth(0.5f); for (int j 0; j row.getLastCellNum(); j) { Cell cell row.getCell(j); String value cell ! null ? cell.getStringCellValue() : ; // 绘制文本 contentStream.beginText(); contentStream.setFont(font, 12); contentStream.newLineAtOffset(xPosition j * colWidth 5, yPosition - i * rowHeight 5); contentStream.showText(value); contentStream.endText(); } // 绘制表格线简化版实际需处理列数 contentStream.moveTo(xPosition, yPosition - i * rowHeight); contentStream.lineTo(xPosition colWidth * 5, yPosition - i * rowHeight); contentStream.stroke(); } contentStream.close(); // 4. 输出 PDF 到响应 response.setContentType(application/pdf); response.setHeader(Content-Disposition, attachment; filename报表.pdf); document.save(response.getOutputStream()); document.close(); workbook.close(); } }PDFBox 方案说明要点说明核心 APIPDDocumentPDPageContentStream绘制内容中文支持需加载中文字体.ttf文件不能像 iText 那样直接用内置字体表格处理需手动绘制表格线和文本无法一键转换 Excel优点Apache License 2.0完全免费商用 方案对比对比项iText 5.xPDFBoxEasyPoi 官方支持✅ 官方依赖 (optional)✅ 4.4.0 支持开源协议AGPL-3.0商业闭源受限Apache 2.0完全免费Excel → PDF 转换PdfImportedPage直接导入需逐行绘制表格中文支持内置itext-asian需加载外部字体开发难度低代码量少高需手动绘制样式保留较完整需手动定义 精进与进阶建议1. 字体文件管理PDFBox 加载中文字体时强烈建议将字体文件放在src/main/resources/fonts/目录而不是硬编码系统路径java// 从 classpath 加载字体避免环境依赖 InputStream fontStream getClass().getResourceAsStream(/fonts/simhei.ttf); PDType0Font font PDType0Font.load(document, fontStream);2. 处理复杂表格PDFBox 手动绘制表格时需要处理合并单元格记录rowspan/colspan信息单元格背景色用contentStream.setNonStrokingColor()填充分页监测yPosition低于页面底部时调用document.addPage()3. 性能优化优化点建议大数据量采用流式处理逐行写入 PDF避免全部加载到内存字体缓存PDType0Font.load()只调用一次复用字体对象页面分页每页行数固定如 A4 约 40 行超出自动换页 参考文献EasyPoi 官方 README — PDF 导出依赖说明itextpdf 5.5.6 itext-asian 5.2.0EasyPoi PDF 导出示例 — iText 转换 Excel 为 PDF 完整代码PDFBox 基础操作 — 创建 PDF、绘制文本和图像iText 中文处理 — BaseFont STSong-Light 字体配置