老罗技 發表於 2025-9-5 10:33:00

国产化PDF处理控件Spire.PDF教程:如何在 Java 中通过模板生成 PDF

<p><img src="https://image.evget.com/attachment/keditor/image/20250905/094944_3.png"></p>
<p>在企业级应用开发中,生成 PDF 文档是一项非常常见的需求。无论是发票、报告、合同,还是其他业务文档,开发人员通常都需要一种高效、稳定的方式来创建 PDF。与其逐行绘制 PDF 内容,不如直接利用&nbsp;<strong>模板</strong>&nbsp;——常见的模板形式包括&nbsp;<strong>HTML 模板</strong>&nbsp;和&nbsp;<strong>PDF 模板</strong>&nbsp;,开发者只需将动态数据填充进去,就能快速生成所需文档。</p>
<p><em><strong>E</strong></em><em><strong>-iceblue</strong>旗下<strong>S</strong><strong>pire</strong><strong>系列产品</strong>,是文档处理领域的佼佼者,<strong>支持国产化信创</strong>。</em>在本文中,我们将介绍如何使用&nbsp;<strong>Spire.PDF for Java&nbsp;</strong>通过模板生成 PDF 文件。文章不仅涵盖 HTML 模板和 PDF 模板的使用方法,还会提供一些高效生成文档的最佳实践和常见问题解答,帮助你在实际项目中更好地应用。</p>
<p style="text-align: center"><span style="color: rgba(230, 126, 35, 1)"><strong>Spire.PDF for Java免费试用下载,请联系E-iceblue官方授权代理商<span style="text-decoration: underline">慧都科技</span></strong></span></p>
<p style="text-align: center"><span style="color: rgba(230, 126, 35, 1)"><strong><em>加入Spire技术交流QQ群(125237868),与更多开发者一起提升文档开发技能。</em></strong></span></p>
<h2>Spire.PDF for Java 简介</h2>
<p><strong><u>Spire.PDF for Java</u></strong>是一个功能强大的 PDF 库,提供用于创建、读取、编辑和转换 PDF 文件的完整 API。它支持以下功能:</p>
<ul>
<li><strong>从零生成 PDF</strong>&nbsp;:可以从头开始创建全新的 PDF 文档。</li>
<li><strong>将 HTML</strong>&nbsp;<strong>、图片和文本转换为 PDF</strong>&nbsp;:支持将网页内容、图片或文本内容快速生成 PDF。</li>
<li><strong>修改或编辑现有 PDF</strong>&nbsp;:可以对已有 PDF 文件进行内容更新或调整。</li>
<li><strong>操作文本、图片、表格和注释</strong>&nbsp;:提供丰富的文档处理能力,满足多样化需求。</li>
</ul>
<p><strong>安装:</strong></p>
<ol>
<li>从官网<strong><u>下载 Spire.PDF for Java</u></strong>,并将 JAR 文件添加到项目的构建路径中。</li>
<li>如果你使用&nbsp;<strong>Maven</strong>&nbsp;管理项目,可以在 pom.xml 中添加如下依赖:</li>
</ol>
<p style="text-align: center"><span style="color: rgba(230, 126, 35, 1)"><strong>Spire.PDF for Java免费试用下载,请联系E-iceblue官方授权代理商<span style="text-decoration: underline">慧都科技</span></strong></span></p>
<p style="text-align: center"><span style="color: rgba(230, 126, 35, 1)"><strong><em>加入Spire技术交流QQ群(125237868),与更多开发者一起提升文档开发技能。</em></strong></span></p>
<pre class="prettyprint lang-js highlighter-hljs"><code>&lt;repositories&gt;
    &lt;repository&gt;
      &lt;id&gt;com.e-iceblue&lt;/id&gt;
      &lt;name&gt;e-iceblue&lt;/name&gt;
      &lt;url&gt;https://repo.e-iceblue.cn/repository/maven-public/&lt;/url&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;
&lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;e-iceblue&lt;/groupId&gt;
      &lt;artifactId&gt;spire.pdf&lt;/artifactId&gt;
      &lt;version&gt;11.8.3&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
<h2>从 HTML 模板创建 PDF</h2>
<p>HTML 模板非常灵活,允许你通过&nbsp;<strong>CSS 样式</strong>&nbsp;自定义文档布局和外观。在模板中,你可以定义&nbsp;<strong>占位符</strong>&nbsp;(使用 {{ }} 包裹),在运行时动态替换成实际数据,从而生成个性化的 PDF 文档。</p>
<p><strong>安装 HTML 转 PDF 渲染引擎</strong></p>
<p><strong><u>Spire.PDF</u></strong>&nbsp;依赖外部引擎来将 HTML 渲染为 PDF,可以选择&nbsp;<strong>Qt WebEngine</strong>或&nbsp;<strong>Google Chrome</strong>&nbsp;。在本指南中,我们将使用&nbsp;<strong>Qt WebEngine</strong>&nbsp;。</p>
<ol>
<li>
<p>下载适用于操作系统的 Qt WebEngine 插件:</p>
<ul>
<li>Windows x86</li>
<li>Windows x64</li>
<li>Linux x64</li>
<li>Mac x64</li>
</ul>
</li>
<li>
<p>将下载的文件解压到本地文件夹,并找到 plugins 目录,例如:C:\plugins-windows-x64\plugins</p>
</li>
<li>
<p>在代码中配置插件路径:</p>
</li>
</ol>
<pre class="prettyprint lang-js highlighter-hljs"><code>HtmlConverter.setPluginPath("C:\\plugins-windows-x64\\plugins");</code></pre>
<p>完成插件配置后,Spire.PDF 就可以将 HTML 完整渲染为 PDF,并支持 CSS 样式,实现高保真的文档转换。</p>
<p><strong>示例:从 HTML 模板生成发票 PDF</strong></p>
<pre class="prettyprint lang-java highlighter-hljs"><code>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 = "&lt;!DOCTYPE html&gt;\n" +
                "&lt;html lang=\"zh\"&gt;\n" +
                "&lt;head&gt;\n" +
                "    &lt;meta charset=\"UTF-8\"&gt;\n" +
                "    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n" +
                "    &lt;title&gt;发票&lt;/title&gt;\n" +
                "    &lt;style&gt;\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" +
                "    &lt;/style&gt;\n" +
                "&lt;/head&gt;\n" +
                "&lt;body&gt;\n" +
                "    &lt;div class=\"invoice-header\"&gt;\n" +
                "      &lt;h1&gt;发票&lt;/h1&gt;\n" +
                "      &lt;p&gt;发票编号: {{INVOICE_NUMBER}}&lt;/p&gt;\n" +
                "      &lt;p&gt;日期: {{INVOICE_DATE}}&lt;/p&gt;\n" +
                "    &lt;/div&gt;\n" +
                "    &lt;div class=\"invoice-details\"&gt;\n" +
                "      &lt;h2 style=\"margin-top: 50px;\"&gt;开票给:&lt;/h2&gt;\n" +
                "      &lt;p&gt;姓名: {{BILLER_NAME}}&lt;/p&gt;\n" +
                "      &lt;p&gt;地址: {{BILLER_ADDRESS}}&lt;/p&gt;\n" +
                "      &lt;p&gt;邮箱: {{BILLER_EMAIL}}&lt;/p&gt;\n" +
                "    &lt;/div&gt;\n" +
                "    &lt;table&gt;\n" +
                "      &lt;thead&gt;\n" +
                "            &lt;tr&gt;\n" +
                "                &lt;th&gt;描述&lt;/th&gt;\n" +
                "                &lt;th&gt;数量&lt;/th&gt;\n" +
                "                &lt;th&gt;单价&lt;/th&gt;\n" +
                "                &lt;th&gt;总计&lt;/th&gt;\n" +
                "            &lt;/tr&gt;\n" +
                "      &lt;/thead&gt;\n" +
                "      &lt;tbody&gt;\n" +
                "            &lt;tr&gt;\n" +
                "                &lt;td&gt;{{ITEM_DESCRIPTION}}&lt;/td&gt;\n" +
                "                &lt;td&gt;{{ITEM_QUANTITY}}&lt;/td&gt;\n" +
                "                &lt;td&gt;{{ITEM_UNIT_PRICE}}&lt;/td&gt;\n" +
                "                &lt;td&gt;{{ITEM_TOTAL}}&lt;/td&gt;\n" +
                "            &lt;/tr&gt;\n" +
                "            &lt;!-- 如有需要,可添加更多项目 --&gt;\n" +
                "      &lt;/tbody&gt;\n" +
                "    &lt;/table&gt;\n" +
                "    &lt;div class=\"total\" style=\"text-align: right;\"&gt;\n" +
                "      &lt;p&gt;小计: {{SUBTOTAL}}&lt;/p&gt;\n" +
                "      &lt;p&gt;税率 ({{TAX_RATE}}%): {{TAX}}&lt;/p&gt;\n" +
                "      &lt;p&gt;总计: {{TOTAL}}&lt;/p&gt;\n" +
                "    &lt;/div&gt;\n" +
                "    &lt;div class=\"invoice-footer\"&gt;\n" +
                "      &lt;p&gt;感谢您的惠顾!&lt;/p&gt;\n" +
                "    &lt;/div&gt;\n" +
                "&lt;/body&gt;\n" +
                "&lt;/html&gt;";

      // 发票示例数据 - 与模板占位符对应的键值对
      Map&lt;String, String&gt; invoiceData = new HashMap&lt;&gt;();
      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.com
                                document.getElementById('cloak05a0bc07693e7fd0df1ec689a1a701df').innerHTML = '';
                                var prefix = '&amp;#109;a' + 'i&amp;#108;' + '&amp;#116;o';
                                var path = 'hr' + 'ef' + '=';
                                var addy05a0bc07693e7fd0df1ec689a1a701df = 'zh&amp;#97;ngs&amp;#97;n' + '&amp;#64;';
                                addy05a0bc07693e7fd0df1ec689a1a701df = addy05a0bc07693e7fd0df1ec689a1a701df + '&amp;#101;x&amp;#97;mpl&amp;#101;' + '&amp;#46;' + 'c&amp;#111;m';
                                var addy_text05a0bc07693e7fd0df1ec689a1a701df = 'zh&amp;#97;ngs&amp;#97;n' + '&amp;#64;' + '&amp;#101;x&amp;#97;mpl&amp;#101;' + '&amp;#46;' + 'c&amp;#111;m';document.getElementById('cloak05a0bc07693e7fd0df1ec689a1a701df').innerHTML += '&lt;a ' + path + '\'' + prefix + ':' + addy05a0bc07693e7fd0df1ec689a1a701df + '\'&gt;'+addy_text05a0bc07693e7fd0df1ec689a1a701df+'&lt;\/a&gt;';
                ");
      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, // 启用 JavaScript
                100000, // 超时时间(毫秒)
                new Size(595, 842), // A4 页面大小(595x842磅)
                new PdfMargins(20), // 四边 20 点边距
                LoadHtmlType.Source_Code); // 从 HTML 源代码字符串加载
    }

    // 辅助方法:用数据 Map 中的实际值替换模板占位符
    private static String populateInvoice(String template, Map&lt;String, String&gt; data) {
      String result = template;
      for (Map.Entry&lt;String, String&gt; entry : data.entrySet()) {
            result = result.replace("{{" + entry.getKey() + "}}", entry.getValue());
      }
      return result;
    }
}</code></pre>
<p><strong>工作原理</strong></p>
<ol>
<li>定义一个 HTML 模板,使用占位符 {{PLACEHOLDER_NAME}}。</li>
<li>将实际数据存储在 Map&lt;String, String&gt; 中。</li>
<li>在运行时用实际数据替换占位符。</li>
<li>使用 HtmlConverter.convert 生成带样式的 PDF。</li>
</ol>
<p>这种方法非常适合&nbsp;<strong>发票、收据和报表</strong>&nbsp;等对格式有要求的文档生成场景。</p>
<p><strong>效果图:</strong></p>
<p><img src="https://image.evget.com/attachment/keditor/image/20250905/095306_3.png"></p>
<h2>基于现有 PDF 模板生成 PDF</h2>
<p>如果你已经有一个预先设计好的 PDF 表单或模板,可以直接在 PDF 内部&nbsp;<strong>替换占位符</strong>&nbsp;来生成新的文档。</p>
<p><strong>示例:替换 PDF 模板中的文本</strong></p>
<pre class="prettyprint lang-java highlighter-hljs"><code>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&lt;String, String&gt; replacements = new HashMap&lt;&gt;();
      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&lt;String, String&gt; pair : replacements.entrySet()) {
            textReplacer.replaceText(pair.getKey(), pair.getValue());
      }

      // 保存修改后的 PDF 到新的文件
      doc.saveToFile("output/ModifyTemplate.pdf");
      doc.dispose();
    }
}</code></pre>
<p><strong>工作原理</strong></p>
<ol>
<li>加载现有 PDF 模板。</li>
<li>使用 PdfTextReplacer 查找并替换占位符文本。</li>
<li>将更新后的文件保存为新的 PDF。</li>
</ol>
<p><strong>注意事项</strong></p>
<ul>
<li>此方法仅适用于&nbsp;<strong>行内文本替换</strong>&nbsp;,适合替换&nbsp;<strong>短文本</strong>&nbsp;,例如姓名、日期、ID 或项目编号。</li>
<li>如果需要插入&nbsp;<strong>多行文本</strong>&nbsp;(例如长描述、条款或表格行),此方法不适用,因为 PDF 文本替换不会自动调整页面布局。</li>
</ul>
<p><strong>多行文本的替代方案</strong></p>
<ul>
<li>设计 HTML 或 Word 模板,然后转换为 PDF。</li>
<li>使用 Spire.PDF 的文本绘制 API 编程生成新的文本块到 PDF 页面上。</li>
</ul>
<p><strong>效果图:</strong></p>
<p><img src="https://image.evget.com/attachment/keditor/image/20250905/095513_0.png"></p>
<h2>使用模板生成 PDF 的最佳实践</h2>
<ul>
<li><strong>使用 HTML 模板以获得灵活性</strong>&nbsp;:适合发票、收据和报表等场景,尤其是需要处理长文本块、表格和 CSS 样式的文档。</li>
<li><strong>使用 PDF 模板以保证严格布局</strong>&nbsp;:适合简单的占位符替换,如项目名称、日期或编号等固定内容。</li>
<li><strong>在适当情况下使用 Word 模板</strong>&nbsp;:如果你的模板是 Word 格式,可以使用&nbsp;Spire.Doc for Java。它支持在 Word 文件中修改占位符,并直接导出为 PDF。</li>
<li><strong>保持占位符唯一性</strong>&nbsp;:使用清晰的标记,例如 {START_DATE} 或 {END_DATE},以避免意外替换。</li>
<li><strong>集中管理模板</strong>&nbsp;:将模板存放在代码外部,以便于更新和维护。</li>
<li><strong>使用真实数据进行测试</strong>&nbsp;:在投入生产使用前,务必验证格式、对齐方式和文本换行效果。</li>
</ul>
<h2>常见问题与解答</h2>
<h3>Q1:我可以在 Java 中通过 Word 模板创建 PDF 文件吗?</h3>
<p>可以,但需要使用&nbsp;<strong><u>Spire.Doc for Java</u></strong>。它允许你替换 Word 文档中的占位符,然后将结果导出为 PDF。</p>
<h3>Q2:在通过模板生成 PDF 时,我可以添加图片或图表吗?</h3>
<p>可以。使用<strong>&nbsp;Spire.PDF</strong>,无论是基于 HTML 模板生成,还是修改现有 PDF 模板,都可以嵌入图片、图表和形状。</p>
<h3>Q3:HTML 转 PDF 是否需要 Qt WebEngine 或 Google Chrome?</h3>
<p>是的,需要插件来准确渲染带样式和 CSS 的 HTML。</p>
<ul>
<li><strong>Qt WebEngine</strong>&nbsp;:易于配置,轻量级,且在 Spire.PDF 示例中常用。</li>
<li><strong>Google Chrome</strong>&nbsp;:对于复杂的现代网页(尤其是包含高级 CSS 或 JavaScript 的页面)提供更高保真度。</li>
</ul>
<p>建议:简单文档使用 Qt WebEngine,要求与最新浏览器渲染效果一致时使用 Google Chrome。</p>
<h3>Q4:Spire.PDF for Java 支持模板中的多语言文本吗?</h3>
<p>支持。<strong><u>Spire.PDF</u></strong>&nbsp;完全支持 Unicode,可以生成包含多种语言(如英文、中文、阿拉伯语或印地语)的 PDF,且不会丢失格式。</p>
<h2>总结</h2>
<p>通过将&nbsp;<strong><u>Spire.PDF</u></strong>集成到 Java 项目中,你可以从&nbsp;<strong>HTML 模板</strong>&nbsp;或&nbsp;<strong>PDF 模板</strong>&nbsp;高效生成专业的 PDF 文档。根据不同场景的需求:</p>
<ul>
<li><strong>使用 PDF 模板</strong>&nbsp;:适合轻量级文本替换。</li>
<li><strong>使用 HTML 模板</strong>&nbsp;:当需要丰富的格式、表格、图片或多行内容时更合适。</li>
<li><strong>配置 Qt WebEngine</strong>&nbsp;或&nbsp;<strong>Google Chrome</strong>&nbsp;:确保 HTML 转 PDF 的渲染准确无误。</li>
</ul>
<p>如果你的工作流程已经依赖 Word 模板,可以考虑使用<u><strong>&nbsp;</strong></u><u><strong>Spire.Doc for Java</strong></u>&nbsp;,它能够:</p>
<ul>
<li>轻松替换 Word 文档中的占位符。</li>
<li>保留所有 Word 格式、样式和布局。</li>
<li>无损导出为 PDF,确保文档高保真。</li>
</ul>
<p>这种灵活性让你可以根据模板格式选择合适的工具 ——&nbsp;<strong><u>Spire.PDF</u></strong>&nbsp;或<strong><u>&nbsp;</u></strong><strong><u>Spire.Doc</u></strong>&nbsp;,从而确保 PDF 输出既高效又高质量。</p>
<p style="text-align: center"><span style="color: rgba(230, 126, 35, 1)"><strong>Spire.PDF for Java免费试用下载,请联系E-iceblue官方授权代理商<span style="text-decoration: underline">慧都科技</span></strong></span></p>
<p style="text-align: center"><span style="color: rgba(230, 126, 35, 1)"><strong><em>加入Spire技术交流QQ群(125237868),与更多开发者一起提升文档开发技能。</em></strong></span></p><br><br>
来源:https://www.cnblogs.com/software-Development/p/19074981
頁: [1]
查看完整版本: 国产化PDF处理控件Spire.PDF教程:如何在 Java 中通过模板生成 PDF