在企業級應用開發中,生成 PDF 文檔是一項非常常見的需求。無論是發票、報告、合同,還是其他業務文檔,開發人員通常都需要一種高效、穩定的方式來創建 PDF。與其逐行繪制 PDF 內容,不如直接利用?模板?——常見的模板形式包括?HTML 模板?和?PDF 模板?,開發者只需將動態數據填充進去,就能快速生成所需文檔。
E-iceblue旗下Spire系列產品,是文檔處理領域的佼佼者,支持國產化信創。在本文中,我們將介紹如何使用?Spire.PDF for Java?通過模板生成 PDF 文件。文章不僅涵蓋 HTML 模板和 PDF 模板的使用方法,還會提供一些高效生成文檔的最佳實踐和常見問題解答,幫助你在實際項目中更好地應用。
Spire.PDF for Java免費試用下載?
Spire.PDF for Java 簡介
Spire.PDF for Java是一個功能強大的 PDF 庫,提供用于創建、讀取、編輯和轉換 PDF 文件的完整 API。它支持以下功能:
- 從零生成 PDF?:可以從頭開始創建全新的 PDF 文檔。
- 將 HTML?、圖片和文本轉換為 PDF?:支持將網頁內容、圖片或文本內容快速生成 PDF。
- 修改或編輯現有 PDF?:可以對已有 PDF 文件進行內容更新或調整。
- 操作文本、圖片、表格和注釋?:提供豐富的文檔處理能力,滿足多樣化需求。
安裝:
- 從官網下載 Spire.PDF for Java,并將 JAR 文件添加到項目的構建路徑中。
- 如果你使用?Maven?管理項目,可以在 pom.xml 中添加如下依賴:
<repositories><repository><id>com.e-iceblue</id><name>e-iceblue</name><url>https://repo.e-iceblue.cn/repository/maven-public/</url></repository> </repositories> <dependencies><dependency><groupId>e-iceblue</groupId><artifactId>spire.pdf</artifactId><version>11.8.3</version></dependency> </dependencies>
從 HTML 模板創建 PDF
HTML 模板非常靈活,允許你通過?CSS 樣式?自定義文檔布局和外觀。在模板中,你可以定義?占位符?(使用 {{ }} 包裹),在運行時動態替換成實際數據,從而生成個性化的 PDF 文檔。
安裝 HTML 轉 PDF 渲染引擎
Spire.PDF?依賴外部引擎來將 HTML 渲染為 PDF,可以選擇?Qt WebEngine或?Google Chrome?。在本指南中,我們將使用?Qt WebEngine?。
-
下載適用于操作系統的 Qt WebEngine 插件:
- Windows x86
- Windows x64
- Linux x64
- Mac x64
-
將下載的文件解壓到本地文件夾,并找到 plugins 目錄,例如:C:\plugins-windows-x64\plugins
-
在代碼中配置插件路徑:
HtmlConverter.setPluginPath("C:\\plugins-windows-x64\\plugins");
完成插件配置后,Spire.PDF 就可以將 HTML 完整渲染為 PDF,并支持 CSS 樣式,實現高保真的文檔轉換。
示例:從 HTML 模板生成發票 PDF
import com.spire.pdf.graphics.PdfMargins; import com.spire.pdf.htmlconverter.LoadHtmlType; import com.spire.pdf.htmlconverter.qt.HtmlConverter; import com.spire.pdf.htmlconverter.qt.Size;import java.util.HashMap; import java.util.Map;public class CreatePdfFromHtmlTemplate {public static void main(String[] args) {// HTML 模板,使用雙大括號 {{}} 作為占位符變量String htmlTemplate = "<!DOCTYPE html>\n" +"<html lang=\"zh\">\n" +"<head>\n" +" <meta charset=\"UTF-8\">\n" +" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +" <title>發票</title>\n" +" <style>\n" +" body {\n" +" font-family: 宋體, sans-serif;\n" +" margin: 20px;\n" +" padding: 20px;\n" +" font-size: 12pt;\n" +" }\n" +" h1 {\n" +" text-align: left;\n" +" font-size: 30pt;\n" +" }\n" +" h2 {\n" +" font-size: 18pt;\n" +" }\n" +" .invoice-header, .invoice-footer {\n" +" text-align: left;\n" +" margin-bottom: 20px;\n" +" }\n" +" .invoice-details {\n" +" margin-bottom: 20px;\n" +" }\n" +" table {\n" +" width: 100%;\n" +" border-collapse: collapse;\n" +" }\n" +" th, td {\n" +" border: 1px solid #ccc;\n" +" padding: 8px;\n" +" text-align: left;\n" +" }\n" +" th {\n" +" background-color: #f2f2f2;\n" +" }\n" +" .total {\n" +" font-weight: bold;\n" +" }\n" +" </style>\n" +"</head>\n" +"<body>\n" +" <div class=\"invoice-header\">\n" +" <h1>發票</h1>\n" +" <p>發票編號: {{INVOICE_NUMBER}}</p>\n" +" <p>日期: {{INVOICE_DATE}}</p>\n" +" </div>\n" +" <div class=\"invoice-details\">\n" +" <h2 style=\"margin-top: 50px;\">開票給:</h2>\n" +" <p>姓名: {{BILLER_NAME}}</p>\n" +" <p>地址: {{BILLER_ADDRESS}}</p>\n" +" <p>郵箱: {{BILLER_EMAIL}}</p>\n" +" </div>\n" +" <table>\n" +" <thead>\n" +" <tr>\n" +" <th>描述</th>\n" +" <th>數量</th>\n" +" <th>單價</th>\n" +" <th>總計</th>\n" +" </tr>\n" +" </thead>\n" +" <tbody>\n" +" <tr>\n" +" <td>{{ITEM_DESCRIPTION}}</td>\n" +" <td>{{ITEM_QUANTITY}}</td>\n" +" <td>{{ITEM_UNIT_PRICE}}</td>\n" +" <td>{{ITEM_TOTAL}}</td>\n" +" </tr>\n" +" <!-- 如有需要,可添加更多項目 -->\n" +" </tbody>\n" +" </table>\n" +" <div class=\"total\" style=\"text-align: right;\">\n" +" <p>小計: {{SUBTOTAL}}</p>\n" +" <p>稅率 ({{TAX_RATE}}%): {{TAX}}</p>\n" +" <p>總計: {{TOTAL}}</p>\n" +" </div>\n" +" <div class=\"invoice-footer\">\n" +" <p>感謝您的惠顧!</p>\n" +" </div>\n" +"</body>\n" +"</html>";// 發票示例數據 - 與模板占位符對應的鍵值對Map<String, String> invoiceData = new HashMap<>();invoiceData.put("INVOICE_NUMBER", "12345");invoiceData.put("INVOICE_DATE", "2025-08-25");invoiceData.put("BILLER_NAME", "張三");invoiceData.put("BILLER_ADDRESS", "北京市朝陽區123號");invoiceData.put("BILLER_EMAIL", "zhangsan@example.comdocument.getElementById('cloak05a0bc07693e7fd0df1ec689a1a701df').innerHTML = '';var prefix = 'ma' + 'il' + 'to';var path = 'hr' + 'ef' + '=';var addy05a0bc07693e7fd0df1ec689a1a701df = 'zhangsan' + '@';addy05a0bc07693e7fd0df1ec689a1a701df = addy05a0bc07693e7fd0df1ec689a1a701df + 'example' + '.' + 'com';var addy_text05a0bc07693e7fd0df1ec689a1a701df = 'zhangsan' + '@' + 'example' + '.' + 'com';document.getElementById('cloak05a0bc07693e7fd0df1ec689a1a701df').innerHTML += '<a ' + path + '\'' + prefix + ':' + addy05a0bc07693e7fd0df1ec689a1a701df + '\'>'+addy_text05a0bc07693e7fd0df1ec689a1a701df+'<\/a>';");invoiceData.put("ITEM_DESCRIPTION", "咨詢服務");invoiceData.put("ITEM_QUANTITY", "10");invoiceData.put("ITEM_UNIT_PRICE", "¥100");invoiceData.put("ITEM_TOTAL", "¥1000");invoiceData.put("SUBTOTAL", "¥1000");invoiceData.put("TAX_RATE", "5");invoiceData.put("TAX", "¥50");invoiceData.put("TOTAL", "¥1050");// 用實際數據填充 HTML 模板String populatedInvoice = populateInvoice(htmlTemplate, invoiceData);// 指定生成 PDF 的輸出路徑String outputFile = "output/HtmlToPdf.pdf";// 指定 HTML 轉 PDF 轉換器插件路徑(QT 插件)String pluginPath = "C:\\plugins-windows-x64\\plugins";// 設置 HTML 轉 PDF 所需的插件路徑HtmlConverter.setPluginPath(pluginPath);// 將 HTML 字符串轉換為 PDF 并指定相關設置HtmlConverter.convert(populatedInvoice, outputFile,true, // 啟用 JavaScript100000, // 超時時間(毫秒)new Size(595, 842), // A4 頁面大小(595x842磅)new PdfMargins(20), // 四邊 20 點邊距LoadHtmlType.Source_Code); // 從 HTML 源代碼字符串加載}// 輔助方法:用數據 Map 中的實際值替換模板占位符private static String populateInvoice(String template, Map<String, String> data) {String result = template;for (Map.Entry<String, String> entry : data.entrySet()) {result = result.replace("{{" + entry.getKey() + "}}", entry.getValue());}return result;} }
工作原理
- 定義一個 HTML 模板,使用占位符 {{PLACEHOLDER_NAME}}。
- 將實際數據存儲在 Map<String, String> 中。
- 在運行時用實際數據替換占位符。
- 使用 HtmlConverter.convert 生成帶樣式的 PDF。
這種方法非常適合?發票、收據和報表?等對格式有要求的文檔生成場景。
效果圖:
基于現有 PDF 模板生成 PDF
如果你已經有一個預先設計好的 PDF 表單或模板,可以直接在 PDF 內部?替換占位符?來生成新的文檔。
示例:替換 PDF 模板中的文本
import com.spire.pdf.PdfDocument; import com.spire.pdf.PdfPageBase; import com.spire.pdf.texts.PdfTextReplaceOptions; import com.spire.pdf.texts.PdfTextReplacer; import com.spire.pdf.texts.ReplaceActionType;import java.util.EnumSet; import java.util.HashMap; import java.util.Map;public class CreatePdfFromPdfTemplate {public static void main(String[] args) {// 創建 PdfDocument 對象PdfDocument doc = new PdfDocument();// 加載現有 PDF 文件doc.loadFromFile("C:\\Users\\Administrator\\Desktop\\Template.pdf");// 創建 PdfTextReplaceOptions 對象并指定替換選項PdfTextReplaceOptions textReplaceOptions = new PdfTextReplaceOptions();textReplaceOptions.setReplaceType(EnumSet.of(ReplaceActionType.WholeWord));// 獲取指定頁面(此處為第一頁)PdfPageBase page = doc.getPages().get(0);// 基于頁面創建 PdfTextReplacer 對象PdfTextReplacer textReplacer = new PdfTextReplacer(page);textReplacer.setOptions(textReplaceOptions);// 定義舊字符串和新字符串的字典Map<String, String> replacements = new HashMap<>();replacements.put("{PROJECT_NAME}", "新網站開發");replacements.put("{PROJECT_NO}", "2023-001");replacements.put("{PROJECT MANAGER}", "王五");replacements.put("{PERIOD}", "2023年第3季度");replacements.put("{START_DATE}", "2023年7月1日");replacements.put("{END_DATE}", "2023年9月30日");// 遍歷字典,替換占位符文本for (Map.Entry<String, String> pair : replacements.entrySet()) {textReplacer.replaceText(pair.getKey(), pair.getValue());}// 保存修改后的 PDF 到新的文件doc.saveToFile("output/ModifyTemplate.pdf");doc.dispose();} }
工作原理
- 加載現有 PDF 模板。
- 使用 PdfTextReplacer 查找并替換占位符文本。
- 將更新后的文件保存為新的 PDF。
注意事項
- 此方法僅適用于?行內文本替換?,適合替換?短文本?,例如姓名、日期、ID 或項目編號。
- 如果需要插入?多行文本?(例如長描述、條款或表格行),此方法不適用,因為 PDF 文本替換不會自動調整頁面布局。
多行文本的替代方案
- 設計 HTML 或 Word 模板,然后轉換為 PDF。
- 使用 Spire.PDF 的文本繪制 API 編程生成新的文本塊到 PDF 頁面上。
效果圖:
使用模板生成 PDF 的最佳實踐
- 使用 HTML 模板以獲得靈活性?:適合發票、收據和報表等場景,尤其是需要處理長文本塊、表格和 CSS 樣式的文檔。
- 使用 PDF 模板以保證嚴格布局?:適合簡單的占位符替換,如項目名稱、日期或編號等固定內容。
- 在適當情況下使用 Word 模板?:如果你的模板是 Word 格式,可以使用?Spire.Doc for Java。它支持在 Word 文件中修改占位符,并直接導出為 PDF。
- 保持占位符唯一性?:使用清晰的標記,例如 {START_DATE} 或 {END_DATE},以避免意外替換。
- 集中管理模板?:將模板存放在代碼外部,以便于更新和維護。
- 使用真實數據進行測試?:在投入生產使用前,務必驗證格式、對齊方式和文本換行效果。
常見問題與解答
Q1:我可以在 Java 中通過 Word 模板創建 PDF 文件嗎?
可以,但需要使用?Spire.Doc for Java。它允許你替換 Word 文檔中的占位符,然后將結果導出為 PDF。
Q2:在通過模板生成 PDF 時,我可以添加圖片或圖表嗎?
可以。使用?Spire.PDF,無論是基于 HTML 模板生成,還是修改現有 PDF 模板,都可以嵌入圖片、圖表和形狀。
Q3:HTML 轉 PDF 是否需要 Qt WebEngine 或 Google Chrome?
是的,需要插件來準確渲染帶樣式和 CSS 的 HTML。
- Qt WebEngine?:易于配置,輕量級,且在 Spire.PDF 示例中常用。
- Google Chrome?:對于復雜的現代網頁(尤其是包含高級 CSS 或 JavaScript 的頁面)提供更高保真度。
建議:簡單文檔使用 Qt WebEngine,要求與最新瀏覽器渲染效果一致時使用 Google Chrome。
Q4:Spire.PDF for Java 支持模板中的多語言文本嗎?
支持。Spire.PDF?完全支持 Unicode,可以生成包含多種語言(如英文、中文、阿拉伯語或印地語)的 PDF,且不會丟失格式。
總結
通過將?Spire.PDF集成到 Java 項目中,你可以從?HTML 模板?或?PDF 模板?高效生成專業的 PDF 文檔。根據不同場景的需求:
- 使用 PDF 模板?:適合輕量級文本替換。
- 使用 HTML 模板?:當需要豐富的格式、表格、圖片或多行內容時更合適。
- 配置 Qt WebEngine?或?Google Chrome?:確保 HTML 轉 PDF 的渲染準確無誤。
如果你的工作流程已經依賴 Word 模板,可以考慮使用?Spire.Doc for Java?,它能夠:
- 輕松替換 Word 文檔中的占位符。
- 保留所有 Word 格式、樣式和布局。
- 無損導出為 PDF,確保文檔高保真。
這種靈活性讓你可以根據模板格式選擇合適的工具 ——?Spire.PDF?或?Spire.Doc?,從而確保 PDF 輸出既高效又高質量。