该页面可以包含自动翻译的文本。

面向 .NET 的 HTML 转 PDF

你可以使用 Docotic.Pdf 库将 HTML 转换为 PDF。该库的免费 HtmlToPdf 加载项可将 HTML、SVG、WEBP 和其他 Web 格式转换为 PDF。

本指南概述了该加载项提供的 HTML 转 PDF 功能,并包含指向相关主题的页面链接,以提供更多细节。

HTML 转 PDF 库内部流程示意图。HTML 文档进入库中,然后生成 PDF 输出。

C# 中 HTML 转 PDF 的基础知识

你需要 HtmlToPdf 加载项、转换代码片段以及许可证密钥。你可以先使用免费的试用密钥。

从 NuGet 安装加载项

Install-Package BitMiracle.Docotic.Pdf.HtmlToPdf

这是推荐方式,因为它会自动处理依赖项和更新。你也可以从包含 Docotic.Pdf 二进制文件的 zip 包中手动安装该加载项,尽管这样更复杂,也更容易出错。

获取许可证密钥

要试用该库,请从 Docotic.Pdf 下载页面获取一个免费的限时许可证密钥。如果你已经购买了许可证,请使用购买后提供给你的代码。

所有 Docotic.Pdf 许可证都包含 HTML 转 PDF 功能。使用该加载项无需额外购买许可证。

添加转换代码

BitMiracle.Docotic.LicenseManager.AddLicenseData("PUT-LICENSE-HERE");

using var converter = await HtmlConverter.CreateAsync();
var html = "<h1>Hello, World<h1>";
using var pdf = await converter.CreatePdfFromStringAsync(html);
pdf.Save("output.pdf");

在代码中,将 AddLicenseData 方法调用里的占位值替换为有效的许可证密钥。

运行代码

转换代码会从字符串中的 HTML 代码生成 PDF。使用默认转换选项时,输出将包含一个 A4 大小的页面。

该库提供了大量用于自定义转换的选项。你可以更改输出大小,或向生成的页面添加页眉和页脚。它还可以转换需要身份验证的资源。

请阅读专门文章中关于将 HTML 转换为 PDF的不同方式,其中对每种方法都做了非常详细的说明。

为什么 Docotic.Pdf 是合适的 HTML 转 PDF 转换器?

在转换过程中保留样式和布局的能力,使 Docotic.Pdf 成为从 HTML 报表、发票和其他文档生成 PDF 的合适选择。该库可从 HTML 以及 SVG 等其他 Web 格式生成像素级精确的 PDF 文档。重用现有 HTML 内容也很容易。

该转换器使用 Google Chrome 渲染引擎。这意味着它具备与顶级 Web 浏览器相同级别的 Web 标准兼容性。

你可以使用 Docotic.Pdf 生成具有现代 CSS、JavaScript 和图像的非常复杂布局的 PDF。它对响应式网页设计也支持得很好。

API 架构概览

只有将 Docotic.Pdf 与免费的 HtmlToPdf 加载项 一起使用时,HTML 转 PDF API 才可用。

该加载项仅提供异步 API。我们将其设计为与 async 事件处理程序和 async 方法配合工作。这样的设计可以优雅地处理长时间运行的任务,而媒体转换就是这类任务的理想示例。

.NET 版本和平台支持

该库和加载项面向 .NET Standard 2.0。这意味着两者都与 .NET 5 到 .NET 10 兼容。此外,也支持 .NET Core 2.0+ 和 .NET Framework 4.6.1+。

你可以在 Windows Forms、WPF、ASP.NET 和控制台应用程序中使用 HTML 转 PDF 功能。该加载项可在云环境和 Docker 容器中运行。

借助该加载项,你可以在 Windows、macOS 和 Linux 环境中从 HTML 生成 PDF。

转换期间会发生什么?

默认情况下,一次转换包含以下阶段:

  1. 你的代码调用 HtmlConverter 类CreateAsync 方法。
  2. 加载项检查当前工作目录中的 .local-chromium 文件夹里是否存在可用版本的 Google Chrome。
  3. 如果没有可用版本,加载项会下载一个并将其解压到 .local-chromium 文件夹中。
  4. 当你的代码调用 CreatePdfAsyncCreatePdfFromStringAsync 方法时,加载项使用 Google Chrome 加载提供的 HTML。
  5. 当内容准备好转换时,加载项指示浏览器生成 PDF。
  6. Google Chrome 使用 Chromium 的渲染能力生成 PDF。
  7. 加载项将包含生成的 PDF 的 PdfDocument 返回给你的代码。

云平台和 Docker 镜像

HtmlToPdf 加载项支持 Azure 和 AWS 云平台,包括无服务器环境。你也可以在 Docker 容器中使用 HTML 转 PDF API。以下是支持的环境列表:

  • Azure: Azure Functions、Azure App Service、Azure VPS
  • Amazon Web Services: AWS ECS、Amazon EC2
  • Docker: Windows 和 Linux 容器。

该库和加载项完全支持动态硬件变更、自动扩缩容以及其他云原生运行时功能。

有关更多信息,请参阅关于在云环境和 Docker 镜像中运行该加载项的文章。

在大多数云场景中,需要无绑定许可证。License FAQ 解释了如何为云应用选择合适的许可证

如何从 HTML 模板生成 PDF

请按照以下简单步骤操作:

  1. 获取模板所需的数据。
  2. 用数据填充模板,生成完整的 HTML。
  3. 使用 Docotic.Pdf 将完整的 HTML 转换为 PDF。

如何从 HTML 模板生成 PDF 的示意图。占位数据在转换为 PDF 之前完成模板。

模板数据通常来自数据库或 API 响应。对于数据库,它可以是单条记录或一组记录。对于 API,它通常是描述一个或多个实体的 JSON 对象。

在下面的示例中,我将使用这个虚构人物:

var person = new
{
    Name = "Alice Johnson",
    Age = 27,
    Email = "alicej@example.com",
    Occupation = "Truck driver"
};

现在我已经有了数据,接下来将介绍准备和填充 HTML 模板的三种方案。尽管对应的模板不同,这三种情况下生成的完整 HTML 都是相同的。

要转换完整的 HTML,请使用我已经提供的代码

命名占位符

命名占位符是用非字母数字符号组成的双分隔符包围的标记。最不容易冲突的分隔符之一是 %%

下面是一个包含命名占位符的模板,以及从中生成完整 HTML 的代码:

var template = @"<head><title>%%NAME%%'s Profile</title></head>
<body>
    <h1>%%NAME%%</h1>
    <p><strong>Age:</strong> %%AGE%%</p>
    <p><strong>Email:</strong> %%EMAIL%%</p>
    <p><strong>Occupation:</strong> %%OCCUPATION%%</p>
</body></html>";

var completeHtml = template
    .Replace("%%NAME%%", person.Name)
    .Replace("%%AGE%%", person.Age.ToString())
    .Replace("%%EMAIL%%", person.Email)
    .Replace("%%OCCUPATION%%", person.Occupation);

在大多数情况下,使用命名占位符是推荐的方法。不过,请记得对你插入占位符位置的任何值进行转义。

模板引擎

当模板非常复杂和/或需要可复用部分时,命名占位符可能不太方便。此时可以改用模板引擎,例如 Handlebars.Net。

下面是一个使用不同模板和代码但生成相同 HTML 的示例:

var template = @"<head><title>{{name}}'s Profile</title></head>
<body>
    <h1>{{name}}</h1>
    <p><strong>Age:</strong> {{age}}</p>
    <p><strong>Email:</strong> {{email}}</p>
    <p><strong>Occupation:</strong> {{occupation}}</p>
</body></html>";

var compiledTemplate = Handlebars.Compile(template);
var completeHtml = compiledTemplate(person);

Handlebars.Net 模板不包含逻辑。如果这让你觉得限制太多,可以试试 Scriban。它提供条件、循环、表达式、函数调用等功能。

位置占位符

这类占位符与命名占位符非常相似,但使用位置编号而不是名称。你已经在 string.Format 方法调用中见过它们。

var template = @"<head><title>{0}'s Profile</title></head>
<body>
    <h1>{1}</h1>
    <p><strong>Age:</strong> {2}</p>
    <p><strong>Email:</strong> {3}</p>
    <p><strong>Occupation:</strong> {4}</p>
</body></html>";

var completeHtml = string.Format(
    template, person.Name, person.Name,
    person.Age, person.Email, person.Occupation);

除最简单的情况外,我建议不要使用位置占位符。原因有两个:

  • 当模板中多次使用某个值时,你必须在调用中多次提供该值。
  • 很容易改动模板中的顺序,却忘记更新代码。

将 ASPX 转换为 PDF

使用 Docotic.Pdf 和免费的 HtmlToPdf 加载项可以将 ASPX 转换为 PDF。过程很直接:

  • 提供 Render 方法的实现,用于累积生成的 HTML。
  • 让 ASP.NET 引擎通过执行服务器端代码和控件来为 ASPX 页面生成 HTML。
  • 将累积的 HTML 转换为 PDF,并在更新后的响应中返回该 PDF。

查看示例代码,了解如何在 ASP.NET Web Forms 应用程序中从 ASPX 页面生成 PDF。该示例应用程序通过创建 HTML 或 PDF 格式的发票演示了上述流程。你可以用同样的方法为报表、对账单和其他文档生成高保真 PDF 版本。

将 SVG 转换为 PDF

借助 Docotic.Pdf 库的 HtmlToPdf 加载项,可以将 SVG 转换为矢量 PDF。你可以将 HtmlConverter 类作为 SVG 转 PDF 转换器使用。下面的 C# 代码展示了一种执行转换的方法:

using var converter = await HtmlConverter.CreateAsync();
var uri = new Uri("https://bitmiracle.com/images/team.svg");
using var pdf = await converter.CreatePdfAsync(uri);
pdf.Save("output.pdf");

上述代码的结果是高质量的矢量 PDF。HtmlToPdf 加载项提供的转换器会使用 SVG 中指定的宽度和高度来确定纵横比。根据 SVG 大小,转换器可能会按比例缩放 SVG 以适配 PDF 页面。

影响输出大小的选项

要生成不同大小的 PDF,请设置页面大小和/或页边距。转换后的 SVG 仍可能按比例缩放。

另一种方式是在 HTML 代码中指定 SVG 的宽度和/或高度,然后转换该 HTML。在输出中,图像将具有指定大小。如果大小大于 PDF 页面,图像的某些部分将不可见。

using var converter = await HtmlConverter.CreateAsync();
var html = $"<img src='https://bitmiracle.com/images/team.svg' width='200' />";
using var pdf = await converter.CreatePdfFromStringAsync(html);
pdf.Save("output.pdf");

将 SVG 文件转换为 PDF

要将 SVG 文件转换为 PDF,请创建一个文件 Uri 并将其传递给 CreatePdfAsync 方法。另一种方式是创建带有 img 标签的 HTML 片段,并将该片段与 CreatePdfFromStringAsync 方法一起使用。如果你在 HTML 代码中使用相对路径,请通过转换选项提供基础 URL

要将多个 SVG 文件转换为 PDF,请创建一个包含多个 img 标签的 HTML 片段,并将其与 CreatePdfFromStringAsync 方法一起使用。如果所有文件都位于同一文件夹中,我建议在 HTML 代码中使用相对路径并提供基础 URL。

将 SVG 添加到 PDF

先使用某个 HtmlConverter 方法将 SVG 转换为 PDF。

using var converter = await HtmlConverter.CreateAsync();
var uri = new Uri("https://bitmiracle.com/images/quote.svg");
using var svgPdf = await converter.CreatePdfAsync(uri);

然后,你可以将生成的 PDF 内容叠加到另一份文档上,或者将该文档与另一份 PDF 合并。

要将 SVG 叠加到 PDF 上,请从转换后文档的第一页创建 XObject,然后将该 XObject 绘制到另一份文档的 PDF 页面上。如下所示:

using var pdf = new PdfDocument("some-other.pdf");
var xObj = pdf.CreateXObject(svgPdf.Pages[0]);

pdf.Pages[0].Canvas.DrawXObject(xObj, 0, 0);
pdf.Save("output.pdf");

要将 SVG 合并到 PDF 中,请使用可用的合并方法之一,将转换后的 PDF 文档与另一份 PDF 合并。

将 WEBP 转换为 PDF

WebP 是一种 Web 格式,因此你可以使用带有 HtmlToPdf 加载项的 Docotic.Pdf 将其转换为 PDF。下面的 C# 代码演示了如何高质量地将 WebP 转换为 PDF:

using var converter = await HtmlConverter.CreateAsync();
var html = $"<img src='https://bitmiracle.com/pdf-library/images/edit/reorder-pages.webp'/>";
using var pdf = await converter.CreatePdfFromStringAsync(html);
pdf.Save("output.pdf");

上面的代码没有为 img 标签指定 widthheight 属性,但建议包含它们。请注意,如果你指定的图像大小大于 PDF 页面,图像的某些部分将不可见。

由于 WebP 是栅格格式,因此放大效果不会很好。我建议使用你预计需要的最大尺寸和分辨率的图像。

要将 WebP 文件转换为 PDF,请使用相同的代码。如果你的 HTML 使用相对路径,请通过加载选项提供基础 URL。在转换本地图像时,请使用文件 Uri 作为基础 URL。

使用 XSLT 将 XML 转换为 PDF

要将 XML 转换为 PDF,首先使用 XSLT 转换将 XML 转换为 HTML。然后使用带有 HtmlToPdf 加载项的 Docotic.Pdf 将生成的 HTML 转换为 PDF。

以下是 C# 的 XML 转 PDF 转换代码:

var transform = CreateTransform("invoice.xsl");
var html = TransformToHtml("invoice.xml", transform);

using var converter = await HtmlConverter.CreateAsync();
using var pdf = await converter.CreatePdfFromStringAsync(html);
pdf.Save("invoice.pdf");

该代码:

  • 在第一行创建一个 XSLT 转换对象。
  • 在第二行将 XML 文件转换为 HTML 文档。
  • 在其余行中将转换结果(HTML 字符串)转换为 PDF。

让我们更仔细地看前两点。第三点已在本节中完整说明。

创建 XSLT 转换

转换过程的第一步是创建一个 XSLT 转换对象。下面的代码演示了如何创建这样的对象:

public static XslCompiledTransform CreateTransform(string xsltFileName)
{
    var transform = new XslCompiledTransform();
    transform.Load(xsltFileName);
    return transform;
}

顾名思义,XslCompiledTransform 会编译提供的样式表,并从中生成 IL 代码。如果你的代码需要批量将 XML 转换为 PDF,建议复用同一个转换对象以提高性能。

将 XML 转换为 HTML

第二步是使用上一步创建的 XSLT 转换对象,根据 XML 生成 HTML。

public static string TransformToHtml(string xmlFileName, XslCompiledTransform transform)
{
    using var xmlReader = XmlReader.Create(xmlFileName);
    using var sw = new StringWriter();
    using var writer = XmlWriter.Create(sw, transform.OutputSettings);
    transform.Transform(xmlReader, null, writer);
    return sw.ToString();
}

该代码使用 XmlReaderXmlWriter,因为它们非常适合大型 XML 文件,并有助于保持较低的内存占用。

XML 转 PDF 转换的示例代码

我们的示例仓库包含一个示例应用程序的 C# 和 VB.NET 版本,该应用程序可将XML 发票转换为 PDF。该示例应用程序包含一个示例 XML 发票和对应的 XSLT 样式表。

当你在现代浏览器中访问返回 XML 的 URL 时,浏览器可以自动应用关联的 XSLT(如果存在),以生成并显示可读的 HTML。只有当 XML 和 XSLT 文件都托管在同一服务器上时,这才有效。为了防止跨域请求,当你直接从本地文件系统打开 XML 文件时,浏览器不会加载或应用该样式表。

权衡与创建 PDF 的替代方式

HTML 转 PDF API 并不是使用 Docotic.Pdf 生成 PDF 的唯一方式,而且它也不总是最有效的。这一节概述了替代方案,以帮助你为具体场景选择合适的选项。

创建 PDF 的几种方式示意图:使用 HTML 转 PDF、Canvas API、基于模板的生成、Layout API,以及组合。

何时选择 HTML 转 PDF

当你的团队已经使用 HTML/CSS 创建文档时,选择 HTML 转 PDF 方案。尤其适用于你的文档类似网页时:发票、采购订单、证书、收据等。

HtmlToPdf 加载项允许团队复用现有的 HTML/CSS 模板,并受益于高保真布局和渲染能力。借助该加载项,获得高质量 PDF 输出的路径可能是最快的。

需要注意的限制

HTML 转 PDF API 使用 Google Chrome HTML 渲染引擎。该引擎功能强大,但也带来额外开销。例如,典型的 HTML 转 PDF 转换会比直接在 PDF 页面 Canvas 上绘制消耗更多 CPU 和内存。这种开销可能会拖慢大批量生成。

浏览器引擎还会增加运行时体积,这在精简 Docker 镜像或资源受限的环境中可能并不理想。例如,在内存消耗和执行时间限制非常严格的无服务器环境中,该 API 可能无法工作。

在 Docotic.Pdf 中生成 PDF 的其他方式

Docotic.Pdf 库提供了多种其他创建文档的方式,每种方式都适用于不同需求:

  • 通过 Canvas API 直接生成 PDF
    适合票据、标签或表单等结构化、可预测的布局。提供最高性能以及对坐标、排版和内容放置的完全控制。

  • 基于模板的 PDF 生成
    当使用已批准、受合规控制的模板时,这通常是最佳选择。你从现有 PDF 开始,填充字段、替换占位符,并按需附加相关文档

  • 使用 Layout API 生成 PDF
    提供页面、容器、图像、文本段落以及其他布局元素等构建块。你通过流畅 API 完全用代码描述 PDF 布局,然后库根据你的布局生成 PDF。

  • 通过其他 PDF 和图像进行组合
    提供一种轻量方式,将对账单、报表、文档包以及其他文档从现有 PDF 和图像中组装出来。你可以将图像转换为 PDF 页面、合并多个 PDF、追加页面,或重用片段。

与其他 HTML 转 PDF 方案的比较

为帮助你为 .NET 选择合适的 HTML 转 PDF 库,下面介绍 Docotic.Pdf 搭配 HtmlToPdf 加载项与其他常见 HTML 转 PDF 方案的对比情况。

关键比较要点

大多数基于浏览器的方案都提供高质量渲染,并完全支持现代 HTML、CSS 和 JavaScript。不过,它们之间仍有重要差异。

方案 适用场景 最适合
搭配 HtmlToPdf 加载项的 Docotic.Pdf 以像素级视觉保真度转换报表、发票和收据 需要 HTML 转 PDF 和 PDF 编辑能力、并由专业支持保障的专业级软件
Puppeteer 当需要浏览器级保真的现代 HTML/CSS/JS 渲染,并且只需要 HTML 转 PDF 输出时 满足免费或开源要求的像素级精确 HTML 转 PDF 生成
IronPDF 当你的团队拥有 Iron Suite 许可证或此前使用过 IronPDF 时 依赖多个 Iron Software 组件的团队
wkhtmltopdf 当需要相对轻量的体积,并且你的 HTML/CSS 简单且不包含外部或不受信任引用时 与现有已使用 wkhtmltopdf 的系统保持兼容

详细比较

查看表中的信息,获取完整情况并自行得出结论。

  搭配 HtmlToPdf 的 Docotic.Pdf Puppeteer IronPDF wkhtmltopdf
引擎 无头 Chrome 无头 Chrome / Chromium 无头 Chrome 旧版 Qt WebKit
渲染保真度 像素级精确 像素级精确 像素级精确 像素级精确,但有怪异行为和限制
HTML5 支持 完全 完全 完全 部分且有限
CSS3 支持 完全 完全 完全 极其有限
JavaScript 支持 完全 完全 完全 部分且过时
与 .NET 代码集成 异步 .NET API 使用 PuppeteerSharp 时为异步 .NET API;否则为 Node.js 脚本。 异步 .NET API 命令行进程或 C# 包装库(如 DinkToPdf)
除 HTML 转换外的 PDF 功能 丰富 有限
支持类型 为潜在客户和现有客户提供专业支持 仅社区支持 为潜在客户和现有客户提供专业支持 仅社区支持
支持可用性 保证响应时间;顶级许可证提供优先支持 依赖志愿者响应;PuppeteerSharp 可通过赞助获得优先支持 保证响应时间;顶级许可证提供优先支持 没有正式支持渠道
维护状态 持续维护中 持续维护中 持续维护中 已停止维护
许可证 商业许可,适用于符合条件的用例可免费使用许可证 Apache-2.0;PuppeteerSharp 为 MIT 商业许可 LGPL-3.0;DinkToPdf 为 MIT
再分发权 所有许可证均免版税 所有许可证均免版税 不包含;需要单独购买 所有许可证均免版税
开发者许可 所有许可证均可无限开发者使用 所有许可证均可无限开发者使用 随许可证级别而异;仅最高级别许可证允许无限开发者 所有许可证均可无限开发者使用
在线许可证验证 不需要在线验证 不执行许可证验证 除高级许可证外都需要 不执行许可证验证

结论

搭配 HtmlToPdf 加载项的 Docotic.Pdf 在提供完整 PDF API 的同时,还能可靠地、高质量地进行 HTML 转 PDF 转换。该库非常适合从 HTML 生成 PDF 报表、发票、收据和其他业务文档,并保持像素级视觉保真度。

该加载项提供一个在本地完全运行的异步 .NET API。你的数据不会离开服务器,使你能够完全控制安全性和隐私。

除了 HTML 转 PDF 转换之外,Docotic.Pdf 还可以添加密码保护到生成的 PDF,并使用数字签名对其进行签名,包括支持 LTV 的签名。

你可以通过合并多个已生成的 PDF 来组装最终文档。如果 PDF 在 HTML 转换或合并后变得过大,该库可以删除文件中的重复对象,并应用其他方法来减小文件大小。为提升阅读体验,Docotic.Pdf 还可以为快速 Web 浏览优化 PDF(线性化 PDF)。

下一步:

常见问题解答

如何为 .NET 选择 HTML 转 PDF 库?

在选择库之前,请先定义并收集你的需求。如果你知道某个候选库无法合并转换后的 PDF,而你的解决方案又需要此功能,那么在评估时就能节省时间。请参阅比较部分,以并排查看 .NET 常见 HTML 转 PDF 库的情况。

为什么我的 HTML 在 PDF 中渲染不正确?

如果你的 HTML 在 Google Chrome 中显示正常,但在生成的 PDF 中不正常,请检查转换选项。确保有足够的宽度容纳内容。HTML 也可能需要在转换前执行 JavaScript

为什么使用 HTML 模板而不是直接使用 PDF API?

使用 HTML 模板能让你的解决方案在文档布局方面非常灵活。你可以利用 HTML 和 CSS 强大的样式能力,轻松更改 PDF 的外观。而且,你无需用 PDF API 去重复在线文档的设计。

如何将 ASPX 转换为 PDF?

要将 ASPX 转换为 PDF,只需让 ASP.NET 引擎为 ASPX 页面生成 HTML,然后使用 Docotic.Pdf 库将该 HTML 转换为 PDF。更多细节请参阅对应章节

如何将 SVG 叠加到 PDF 上?

要将 SVG 叠加到 PDF 上,先从 SVG 生成 PDF,然后从生成文档的第一页创建 XObject。由于 XObject 具有透明背景,你可以将其放置在另一份文档的 PDF 页面上方。

如何向生成的 PDF 添加水印?

要向从 HTML 生成的 PDF 文档添加水印,请创建一个 XObject,用水印内容填充它,然后将该 XObject 绘制到文档页面上方。水印可以使用矢量图形、图像和文本。

Docotic.Pdf 是否比 wkhtmltopdf 更好?

Docotic.Pdf 完全支持现代 HTML、CSS 和 JavaScript,而 wkhtmltopdf 在现代 Web 文档上的渲染通常不一致。此外,Docotic.Pdf 提供了超出 HTML 转 PDF 转换之外的 API。例如,该库可以使用支持 LTV 的数字签名对 PDF 进行签名,而 wkhtmltopdf 只能转换 HTML。