spring boot 实现pdf模板导出
实现背景:
在某些场景中,我们需要从数据库或其他来源获取的数据信息,动态的导出Pdf文件,如准考证的打印等。这时我们需要借助第三方依赖包—itextpdf 来实现此需求。
一、制作PDF模板
1、在Word内制作模板
因为PDF常用的软件不支持编辑,所以先用Word工具,如WPS或者Office新建一个空白Word文档,里面制作出自己想要的样式。

2、将Word转换成PDF形式
将设置好的Word文档转换成PDF形式,保存起来。

3、编辑PDF准备bia
用Adobe Acrobat DC 软件打开保存好的PDF模板文件,点击右下角的更多工具按钮
通过网盘分享的文件:Acrobat Pro DC2022(64bit).zip
链接: https://pan.baidu.com/s/1vaVsoRfUHnpil36Gy1zvuQ?pwd=Bxh1 提取码: Bxh1
Adobe Acrobat DC安装参考地址:https://blog.csdn.net/qq_44111805/article/details/1283533
以上参考网址:https://blog.csdn.net/L28298129/article/details/118732743?spm=1001.2014.3001.5506
下面新增linux支持:
Linux 字体环境配置
二、Linux 字体环境配置
1. 安装字体依赖
确保系统已安装字体工具和中文支持:
2. 部署字体文件
将 SIMSUN.TTC 复制到字体目录并生成索引:
3. 验证字体可用性
检查字体是否加载成功:
代码服务层如下:
@Override public void exportPtf(HttpServletRequest request, HttpServletResponse response, String id) throws Exception { LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal(); SysEmployee employee = sysEmployeeService.getById(user.getId()); String organizeName = "无锡伟达"; if (employee != null && employee.getOrgId() != null) { SysOrganize org = organizeService.getById(employee.getOrgId()); organizeName = org != null ? org.getOrganizeName() : "无锡伟达"; } DetectionReportDto detectionReportDto = queryById(id); List<DetectionReportItemDto> items = detectionReportDto.getReportItems(); String fjTag = ""; if (items != null && items.size() > 1) { fjTag = items.size() + ""; } String fileName = "产品检验报告"; String titleStr = "产品检验报告"; // 模板存放地址 String templateUrl = uploadpath + File.separator + "other" + File.separator; switch (detectionReportDto.getReportType()) { case 4:// 过程检验 templateUrl = templateUrl + "detectionreportCP" + fjTag + ".pdf"; break; case 2: // 产品检验 templateUrl = templateUrl + "detectionreportCP" + fjTag + ".pdf"; break; case 1: // 原料检验 templateUrl = templateUrl + "detectionreportYL.pdf"; fileName = "原料检验报告"; titleStr = "原料检验报告"; break; default: templateUrl = templateUrl + "detectionreportCP" + fjTag + ".pdf"; break; } fileName = fileName + "[" + detectionReportDto.getReportNumber() + "]"; // 设置响应头 response.setCharacterEncoding("UTF-8"); response.setContentType("Application/pdf"); response.setHeader("Content-Disposition", "attachment;fileName=" + templateUrl); OutputStream out = null; ByteArrayOutputStream bos = null; PdfStamper stamper = null; PdfReader reader = null; try { // 保存到本地 // out = new FileOutputStream(fileName); // 输出到浏览器端 out = response.getOutputStream(); // 读取PDF模板表单 reader = new PdfReader(templateUrl); // 字节数组流,用来缓存文件流 bos = new ByteArrayOutputStream(); // 根据模板表单生成一个新的PDF stamper = new PdfStamper(reader, bos); // 获取新生成的PDF表单 AcroFields form = stamper.getAcroFields(); // 给表单生成中文字体,这里采用系统字体,不设置的话,中文显示会有问题 String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("win")) { // Windows 路径(项目内字体文件) BaseFont font = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); form.addSubstitutionFont(font); } else { // Linux 路径(推荐使用相对路径或资源目录) BaseFont font = BaseFont.createFont("/usr/share/fonts/myapp/SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); form.addSubstitutionFont(font); } // 装配数据 Map<String, Object> data = new HashMap<>(); data.put("titleStr", organizeName + titleStr); data.put("organizeName", organizeName); data.put("goodsNameStr", "NO." + detectionReportDto.getReportNumber()); data.put("createTime", DateUtils.date2Str(detectionReportDto.getCreateTime(), DateUtils.date_sdf.get())); data.put("goodsName", detectionReportDto.getGoodsName()); String productionTime = DateUtils.date2Str(detectionReportDto.getProductionStartTime(), DateUtils.date_sdf_wz.get()) + "至" + DateUtils.date2Str(detectionReportDto.getProductionEndTime(), DateUtils.date_sdf_wz.get()); data.put("productionTime", productionTime.equals("null至null") ? " " : productionTime); data.put("models", detectionReportDto.getModels() != null ? String.join(",", detectionReportDto.getModels()) : ""); data.put("batches", detectionReportDto.getBatches() != null ? String.join(",", detectionReportDto.getBatches()) : ""); data.put("batchCount", detectionReportDto.getBatchCount() + detectionReportDto.getMeasuringUnitName()); data.put("sampleCount", detectionReportDto.getSampleCount() + detectionReportDto.getMeasuringUnitName()); data.put("comprehensiveJudgment", detectionReportDto.getComprehensiveJudgment() == 1 ? "合格" : "不合格"); data.put("comprehensiveJudgmentCont", detectionReportDto.getComprehensiveJudgmentCont()); data.put("detectionDate", DateUtils.date2Str(detectionReportDto.getDetectionDate(), DateUtils.date_sdf.get())); data.put("employeeName", detectionReportDto.getEmployeeName()); data.put("detectionStandardName", detectionReportDto.getDetectionStandardName()); data.put("organizeName", organizeName); // 动态行 if (items != null && items.size() > 0) {// 动态列有点复杂,时间紧,先按不同模板来 if (items.size() == 1) { DetectionReportItemDto dto = items.get(0); data.put("fill_1", dto.getDetectionStandardItemName()); data.put("fill_2", dto.getDetectionStandardItemRequire()); data.put("fill_3", dto.getDetectionResult() == 1 ? "合格" : "不合格"); data.put("fill_3", dto.getDetectionConclusion()); } if (items.size() == 2) { DetectionReportItemDto dto = items.get(0); data.put("fill_1", dto.getDetectionStandardItemName()); data.put("fill_2", dto.getDetectionStandardItemRequire()); data.put("fill_3", dto.getDetectionResult() == 1 ? "合格" : "不合格"); data.put("fill_3", dto.getDetectionConclusion()); DetectionReportItemDto dto2 = items.get(1); data.put("fill_11", dto2.getDetectionStandardItemName()); data.put("fill_21", dto2.getDetectionStandardItemRequire()); data.put("fill_31", dto2.getDetectionResult() == 1 ? "合格" : "不合格"); data.put("fill_31", dto2.getDetectionConclusion()); } if (items.size() == 3) { DetectionReportItemDto dto = items.get(0); data.put("fill_1", dto.getDetectionStandardItemName()); data.put("fill_2", dto.getDetectionStandardItemRequire()); data.put("fill_3", dto.getDetectionResult() == 1 ? "合格" : "不合格"); data.put("fill_3", dto.getDetectionConclusion()); DetectionReportItemDto dto2 = items.get(1); data.put("fill_11", dto2.getDetectionStandardItemName()); data.put("fill_21", dto2.getDetectionStandardItemRequire()); data.put("fill_31", dto2.getDetectionResult() == 1 ? "合格" : "不合格"); data.put("fill_31", dto2.getDetectionConclusion()); DetectionReportItemDto dto3 = items.get(2); data.put("fill_12", dto3.getDetectionStandardItemName()); data.put("fill_22", dto3.getDetectionStandardItemRequire()); data.put("fill_32", dto3.getDetectionResult() == 1 ? "合格" : "不合格"); data.put("fill_32", dto3.getDetectionConclusion()); } } // 遍历data,给pdf表单赋值 for (String key : data.keySet()) { form.setField(key, data.get(key).toString()); } // 表明该PDF不可修改 stamper.setFormFlattening(true); // 关闭资源 stamper.close(); // 将ByteArray字节数组中的流输出到out中(即输出到浏览器) Document doc = new Document(); PdfCopy copy = new PdfCopy(doc, out); doc.open(); PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1); copy.addPage(importPage); doc.close(); log.info("*****************************PDF导出成功*********************************"); } catch (Exception e) { e.printStackTrace(); } finally { try { if (out != null) { out.flush(); out.close(); } if (reader != null) { reader.close(); } } catch (Exception e) { e.printStackTrace(); } } }

浙公网安备 33010602011771号