Skip to content
ComPDF

通过 HTML 模板生成 PDF

整体流程概述

通用 HTML 模板生成 PDF 功能需要一个 HTML 模板以及用来填充模板的结构化数据,就是 JSON 数据,从而生成一个标准的 HTML。再使用生成 PDF 功能相应的接口就可以将标准的 HTML 转成 PDF 文档。

构建 HTML 模板

模板是一个 HTML 文件,还需要一个与模板匹配的 JSON 数据。 JSON 数据是一个正常的 JSON 文件。HTML 模板文件需要结合 JSON 数据以生成一个标准的 HTML。 结合 JSON 数据和 HTML 模版生成 HTML 的过程支持变量、if 语句、for 循环、四则运算、常用函数。

HTML 模板示例:

html
<!doctype html>
<html>
<body style="margin: 0; padding: 0;">
<table cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; margin: 0 auto">
  <tr>
    <td style="padding-top: 40px;">
      <img
          src="{% if compdfkit %}images/logo.png{% else if compdfkit2 %}images/logo2.png{% else %}images/logo3.png{% endif %}"
          alt="PDF Technologies"
          width="203"
          height="50">
    </td>
    <td style="padding-top: 40px; text-align: right;">
      <img src="images/invoice.png" alt="invoice" width="132">
      <td style="border: 1px solid #8A8EA8; padding: 2px 10px;">{{billNo}}</td>
    </td>
  </tr>
</table>
<table cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;">
  <!-- {% set totalprice = 0 %} -->
  <!-- {% for item in items %} -->
  <tr style="height:64px;color:#333;">
    <td style="width:70px;height:70px;border-bottom: 2px solid #F3F3F3; padding-left: 10px; text-align: left;">
      {{ item.index }}
    </td>
    <td style="width: 160px;border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;text-align:left;">
      <div>
        <p style="font-size: 13px; line-height: 15px; font-weight: bold; color: #121E3F; margin: 0;">
          {{ item.product }}
        </p>
        <p style="font-size: 11px; line-height: 12px; padding-top: 4px; color: #5F6881; margin: 0;">
          {{ item.startDateAndEndDate }}
        </p>
      </div>
    </td>
    <td style="width: 130px;border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;text-align:left;">
      {{ item.paymentCycle }}
    </td>
    <td style="width: 100px;border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;text-align:left;">
      {{ item.gearLevel }}
    </td>
    <td style="width: 100px;text-align:left;border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;">
      $ {{ item.price }}
    </td>
  </tr>
  <!-- {% set totalprice = totalprice + item.price %} -->
  <!-- {% endfor %} -->
  <tr>
    <td style="width:70px;"></td>
    <td style="width:160px;"></td>
    <td colspan="2" style="width: 100px; text-align:right; font-weight: bold; font-size: 16px; line-height: 18px; color: #121E3F; padding-right: 72px;">Total:</td>
    <td style="width: 100px; text-align:left; font-weight: bold; font-size: 16px; line-height: 18px; color: #121E3F;">$ {{round(totalprice * (1 + tax * 0.01), 2)}}</td>
  </tr>
</table>
</body>
</html>

如上面示例中所示,HTML 模板中,存在一些非 HTML 标准的内容,比如:{% if compdfkit %}{{billNo}}<!-- {% set totalprice = totalprice + item.price %} --><!-- {% for item in items %} -->等。这些非 HTML 标准的内容包括变量、if 语句、for 循环、四则运算、常用函数,这几种类型。

变量

html
<td style="border: 1px solid #8A8EA8; padding: 2px 10px;">{{billNo}}</td>

上面{{billNo}}就是一个变量,即变量需要{{ }}框住, 对应JSON文件中名为billNo的条目。

如果 JSON 文件中不存在相应名字,需要先定义。下面是定义变量的示例。

html
<!-- {% set totalprice = 0 %} -->

示例模板中,上面一行代码定义了一个totalprice变量。和前面的billNo变量一样,{{ }}框住后使用:{{totalprice}}

四则运算

html
<!-- {% set totalprice = totalprice + item.price %} -->

上面一行代码对totalprice进行计算,加减乘除都支持。

if 语句

html
<img
     src="{% if compdfkit %}images/logo.png{% else if compdfkit2 %}images/logo2.png{% else %}images/logo3.png{% endif %}"
     alt="PDF Technologies"
     width="203"
     height="50">

其中 {% if compdfkit %} … {% else if compdfkit2 %}...{% else %}...{% endif %} 是一个完整的 if 语句结构,else if 和 else 可省略。compdfkitcompdfkit2对应着 JSON 文件中同名的条目。

for 循环

html
<!-- {% set totalprice = 0 %} -->
<!-- {% for item in items %} -->
               ……….
      <!-- {% set totalprice = totalprice + item.price %} -->
<!-- {% endfor %} -->

{% for item in items %}...{% endfor %}是一个 for 循环的结构。其中 items 是 JSON 文件中的一个数组类型的数据。

常用函数

html
<td style="width: 100px; text-align:left; font-weight: bold; font-size: 16px; line-height: 18px; color: #121E3F;">$ {{round(totalprice * (1 + tax * 0.01), 2)}}</td>

其中,round是函数,可以传入变量做为函数参数。totalpricetax是变量。整个函数用{{ }}框住。

准备 JSON 数据

准备标准格式的 JSON 数据,用来和 HTML 模板结合,将数据填充到模板中,以生成标准的 HTML。JSON 数据示例:

json
{
    "address": "456 Oak Avenue",
    "billNo": "2345678901",
    "company": "TechCorp Ltd.",
    "country": "Canada",
    "email": "[email protected]",
    "firstName": "Alice",
    "gearLevel": "Pro",
    "compdfkit": false,
    "compdfkit2": true,
    "invoiceDate": "2025-01-15",
    "lastName": "Smith",
    "paymentCycle": "Yearly",
    "price": "1200",
    "province": "Ontario",
    "startDateAndEndDate": "2025-01-15 to 2025-02-15",
    "tax": 8,
    "zip": "K1A 0A6",
    "items": [
        {
            "index": 1,
            "product": "ComPDFKit Pro",
            "startDateAndEndDate": "2025-01-15 to 2025-02-15",
            "paymentCycle": "Yearly",
            "gearLevel": "Pro",
            "price": 800
        },
        {
            "index": 2,
            "product": "ComPDFKit API",
            "startDateAndEndDate": "2025-01-15 to 2025-02-15",
            "paymentCycle": "Monthly",
            "gearLevel": "Basic",
            "price": 400
        }
    ]
}

填充模板,生成 PDF

在进行生成 PDF 之前,需要使用下面这段代码对 PDF 生成功能模块进行 SDK license 认证。

注意:需要将您的 license 替换到 LicenseVerify() 方法中。

c#
public static bool LicenseVerify()
{
    if (!CPDFGeneration.LoadNativeLibrary())
        return false;
    
    LicenseErrorCode errorCode = CPDFGeneration.LicenseVerify("Input your license here");
    return (verifyResult == LicenseErrorCode.LICENSE_SUCCESS);
}

JSON 文件与 HTML 模板结合转换为 PDF:

c#
// HTML模板文件路径
string templatePath = "/templatePath.html";
// JSON文件路径
string jsonPath = "/jsonPath.json";
// 生成的HTML文件路径
string outputHtml = "/outHtml.html";
// 生成的PDF文件路径
string outputPdf = "/html2pdfOut.pdf";

// 将JSON文件与HTML模板结合生成HTML文件
CHtmlConverter.RenderAndConvertToPdf(templatePath, jsonPath, outputHtml);

// 开始转换HTML文件为PDF
CHtmlConverter.ConvertToPdf(outputHtml, outputPdf);

上面示例是先将 JSON 文件与 HTML 模板结合生成 HTML 内容,再将 HTML 内容转成 PDF, 分两步进行的,也可以直接转成 PDF:

c#
// HTML模板文件路径
string templatePath = "/templatePath.html";
// JSON文件路径
string jsonPath = "/jsonPath.json";
// 生成的PDF文件路径
string outputPdf = "/html2pdfOut.pdf";

// 将JSON文件与HTML模板结合并直接转换为PDF
CHtmlConverter.RenderAndConvertToPdf(templatePath, jsonPath, outputPdf);

生成的 PDF 示例

HTML转PDF示例

配置属性

在将 HTML 转换为 PDF 时,您可以配置某些属性,如基础 URI、页面大小和字体。

c#
// HTML模板文件路径
string templatePath = "/templatePath.html";
// JSON文件路径
string jsonPath = "/jsonPath.json";
// 生成的PDF文件路径
string outputPdf = "/html2pdfOut.pdf";

// 配置属性
CConverterProperties properties = new CConverterProperties();
// 设置基础URI
properties.SetBaseUri("/baseUri/");
// 设置页面大小
CSize pageSize = new CSize { Width = 595, Height = 842 };
properties.SetPageSize(pageSize);
// 设置字体
CFontProvider fontProvider = new CFontProvider();
fontProvider.AddDirectory("/fontDir/");
properties.SetFontProvider(fontProvider);

// 使用属性配置将HTML转换为PDF
CHtmlConverter.RenderAndConvertToPdf(templatePath, jsonPath, outputPdf, properties);

设置字体

该示例使用了 fontProvider.AddDirectory("/test/fontDir/"),您应该在 /fontDir/目录中提供一些字体文件,这样 HTML 文件中的文本就可以使用这些提供的字体了。下面是部分 HTML 示例代码,其中 span 标签内的文本使用了 Sarabun 字体。Sarabun 是一个被提供的字体,相应的字体文件应放置在合适的目录中。

html
<style data-dito-stylesheet-name="setFonts">@font-face {
    font-family: "Sarabun";
}
@font-face {
    font-family: "Sarabun";
    font-style: italic;
}
@font-face {
    font-family: "SarabunThin";
}
@font-face {
    font-family: "SarabunsemiBold";
}</style>

<div style="margin-left:0in;margin-top:0pt;margin-bottom:0pt">
  <span style="font-family:Sarabun">
    <span style="color:black">
      <span style="font-size:26px">(PEA GECC Internal Audit)</span>
    </span>
  </span>
</div>

在转换过程中,HTML 模板和 JSON 数据可以作为内容字符串文件流文件对象文件路径提供。生成的 PDF 可以输出到文件流文件对象文件路径

之前的示例使用了文件路径,而下面是一个使用文件流的示例:

c#
string templatePath = "/templatePath.html";
string jsonPath = "/jsonPath.json";
string outputPdf = "/html2pdfOut.pdf";

FileStream templateStream = File.OpenRead(templatePath);
FileStream jsonStream = File.OpenRead(jsonPath);
FileStream outputPdfStream = File.Create(outputPdf);
CHtmlConverter.RenderAndConvertToPdf(templateStream, jsonStream, outputPdfStream);

使用内容字符串:

c#
string templatePath = "/templatePath.html";
string jsonPath = "/jsonPath.json";
string outputPdf = "/html2pdfOut.pdf";

string templateContent = File.ReadAllText(templatePath);
string jsonContent = File.ReadAllText(jsonPath);
FileStream outputPdfStream = File.Create(outputPdf);
CHtmlConverter.RenderAndConvertToPdf(templatePath, jsonPath, outputPdfStream);

使用文件对象:

c#
string templatePath = "/templatePath.html";
string jsonPath = "/jsonPath.json";
string outputPdf = "/html2pdfOut.pdf";

FileInfo htmlFileInfo = new FileInfo(templatePath);
FileInfo jsonFileInfo = new FileInfo(jsonPath);
FileInfo pdfFileInfo = new FileInfo(outputPdf);
CHtmlConverter.RenderAndConvertToPdf(htmlFileInfo, jsonFileInfo, pdfFileInfo);