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號