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

使用 C# 和 VB.NET 将 HTML 转换为 PDF

如果您已经投入大量时间和金钱创建了 HTML 格式的内容,您可能希望将其转换为 PDF 文件。对于任何想要避免重复工作的人来说,这都是一个自然的选择。

本文将详细介绍如何使用 Docotic.Pdf 及其免费的 HtmlToPdf 插件在 .NET 中将 HTML 转换为 PDF。

有关 Docotic.Pdf 为何是最佳选择、如何安装该插件以及转换过程的内部工作原理,请参阅HTML 转 PDF API 概述页面。

HTML 转 PDF

简单的 HTML 转 PDF C# 转换

首先,安装插件。

Install-Package BitMiracle.Docotic.Pdf.HtmlToPdf

使用HTML 转 PDF API,C# 转换代码可以如下所示:

static async Task ConvertUrlToPdfAsync(string urlString, string pdfFileName)
{
    using var converter = await HtmlConverter.CreateAsync();
    using var pdf = await converter.CreatePdfAsync(new Uri(urlString));
    pdf.Save(pdfFileName);
}

操作非常简单。只需两次调用即可生成 PDF 文档。

代码会创建一个转换器实例,并使用它来从 HTML 生成 PDF。您可以编辑 PDF文档,或使用数字签名对其进行签名。为简单起见,示例代码会直接保存文档。

如您所见,该 API 是异步的,完全不提供同步方法。

在同步代码中使用异步 API

有些情况下,您需要从同步代码中调用 API。例如,当您的控制台应用程序使用旧版本的 C# 且没有异步 Main 方法时。不用担心,您仍然可以在应用程序中使用该插件。

以下代码展示了如何在常规同步方法中将 URL 转换为 PDF:

Task.Run(async () =>
{
    using var converter = await HtmlConverter.CreateAsync();
    var uri = new Uri("https://bitmiracle.com/pdf-library/html-pdf/");
    using var pdf = await converter.CreatePdfAsync(uri);
    pdf.Save("output.pdf");
}).GetAwaiter().GetResult();

VB.NET 应用程序使用类似的代码。以下代码片段展示了如何在同步 VB.NET 代码中将 HTML 转换为 PDF。

Task.Run(
    Async Function()
        Using converter = Await HtmlConverter.CreateAsync()
            Dim uri = New Uri("https://bitmiracle.com/pdf-library/html-pdf/")
            Using pdf = Await converter.CreatePdfAsync(uri)
                pdf.Save("output.pdf")
            End Using
        End Using
    End Function
).GetAwaiter().GetResult()

请注意,通常不建议同步调用异步方法,因此只有在别无选择时才使用包装器。

示例代码

我们提供控制台应用程序、Windows Forms 应用程序和 WPF 应用程序的示例代码。您可以从我们的 GitHub 代码库下载完整的测试项目:

此外,还有一组HTML 转 PDF示例。每个示例都提供 C# 和 VB.NET 版本。

使用 C# 和 VB.NET 通过 HTML 字符串或文件创建 PDF

使用此 API 可以轻松地将 HTML 字符串转换为 PDF。该字符串可以包含完整的 HTML 文档,也可以只是其中的一个片段。转换器会根据 HTML 代码为您创建 PDF。

using var converter = await HtmlConverter.CreateAsync();

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

HTML 代码可以包含对图片、脚本和 CSS 文件的相对引用。要正确转换此类代码,您需要为 HTML 中的所有相对链接指定一个基本 URL。以下是如何使用转换选项指定基本 URL:

using var converter = await HtmlConverter.CreateAsync();

var incompleteHtml = "<img src=\"/images/team.svg\"></img>";

var options = new HtmlConversionOptions();
options.Load.BaseUri = new Uri("https://bitmiracle.com/");

using var pdf = await converter.CreatePdfFromStringAsync(incompleteHtml, options);
pdf.Save("output.pdf");

我们的 GitHub 存储库包含完整的测试项目

转换 HTML 文件与转换 URL 几乎相同。只需使用接受路径而非 URL 的 CreatePdfAsync 重载即可。在 C# 或 VB.NET 代码中将 HTML 文件转换为 PDF 时,也支持基本 URL 和其他选项。

var sampleHtmlPath = @"C:\path\to\sample.html";
using var pdf = await converter.CreatePdfAsync(sampleHtmlPath);
pdf.Save("output.pdf");

您还可以使用 API 将 SVG 图像转换为 PDF

使用自定义页面尺寸、边距和缩放比例

处理布局较宽的网页时,您可以增大输出 PDF 的尺寸,或者缩小内容以适应 PDF 页面。为了更好地定位缩放后的内容,您还可以设置页边距。

缩放良好的 PDF 可以提供更佳的阅读体验,因为读者无需放大或缩小即可正确查看内容。如果 HTML 文档由于字体过小而难以阅读,您可以放大内容。

默认情况下,API 生成的 PDF 页面大小为 A4。没有页边距,也没有缩放。您可以使用转换选项更改这些设置。

请参阅如何设置从 HTML 生成 PDF 时的缩放因子和页边距。

using var converter = await HtmlConverter.CreateAsync();

var html = "<html><head><style>body { background-color: coral; margin-top: 100px;}</style></head>" +
"<body><h1>Did you notice the margins and the scale?</h1></body></html>";

var options = new HtmlConversionOptions();
options.Page.MarginLeft = 10;
options.Page.MarginTop = 20;
options.Page.MarginRight = 30;
options.Page.MarginBottom = 40;
options.Page.Scale = 1.5;

using var pdf = await converter.CreatePdfFromStringAsync(html, options);
pdf.Save("output.pdf");

Docotic.Pdf 示例存储库包含完整的项目

HTML 转 PDF API 可以在生成的页面上添加可重复的页眉/页脚块。转换器会根据页面选项中指定的 HTML 模板创建这些块。我们建议在模板中使用内联样式和图像数据 URI。

转换器会将页眉和页脚放置在页面边距内。由于默认页面边距较小,页眉和页脚的内容可能无法显示。我们建议显式指定上边距和下边距。其大小应分别与页眉和页脚的大小相匹配。

了解如何将 HTML 转换为 PDF 并添加页眉和页脚。

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
options.Page.HeaderTemplate = File.ReadAllText("header-template.html");
options.Page.MarginTop = 50;

options.Page.FooterTemplate = File.ReadAllText("footer-template.html");
options.Page.MarginBottom = 50;

var url = new Uri("https://www.iana.org/numbers");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

这些模板使用标准的 HTML 代码,并支持一些变量。这些变量包括 datetitleurlpageNumbertotalPages页眉模板页脚模板 都支持相同的变量集。

完整的测试项目和模板代码位于 Docotic.Pdf 示例库中。示例代码展示了如何在模板中使用变量和数据 URI。

受密码保护的 HTML 转 PDF C# 转换

某些网页需要身份验证才能访问。当您访问需要 HTTP 身份验证的安全 URL 时,浏览器会要求您提供用户名和密码。

使用转换选项,您可以指示 API 为需要登录的网页提供凭据。

以下 C# 代码演示了如何将受密码保护的 HTML 转换为 PDF。

using var converter = await HtmlConverter.CreateAsync();
var url = new Uri("http://httpbin.org/basic-auth/foo/bar");

var options = new HtmlConversionOptions();
options.Authentication.SetCredentials("foo", "bar");

using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

在示例库中查找完整的工作示例

如果页面需要设置一些 cookie 才能正常运行,也很容易。只需将这些 cookie 添加到选项中即可。方法如下:

var options = new HtmlConversionOptions();
options.Cookies.Add(new Cookie("sessionID", "my-session-ID"));

using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

延迟转换开始

默认情况下,页面加载后会立即开始转换。如果页面加载后持续更新一段时间,延迟 HTML 到 PDF 的转换会很有帮助。这种情况在处理由 JavaScript 或 AJAX 调用生成的动态内容时很常见。

Acid 3 测试就是一个典型的例子,它能从转换前的延迟中获益。该测试会执行一系列检查,以评估浏览器正确渲染复杂网页的能力。这些检查需要时间。尝试更改以下代码中的等待时间,看看它如何影响转换结果。

var options = new HtmlConversionOptions();
options.Start.SetStartAfterDelay(10 * 1000);

using var converter = await HtmlConverter.CreateAsync();
var url = new Uri("http://acid3.acidtests.org/");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

以上代码展示了如何延迟将 HTML 转换为 PDF。虽然额外的时间有助于获得更好的转换结果,但请注意,添加延迟可能会影响性能。延迟时间不足则会影响转换质量。除了使用延迟之外,另一种方法是使用脚本,该脚本会在页面准备就绪后一直执行。

您可以在 Docotic.Pdf 示例库中获取完整的测试项目

转换前执行 ​​JavaScript

该插件 API 提供了一种在转换之前运行 JavaScript 代码的方法。该代码可以动态生成或修改 HTML 内容。例如,它可以切换元素,或实现动态内容加载。

以下代码展示了如何延迟 HTML 到 PDF 的转换,直到 JavaScript 代码执行完毕。

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
var js = @"document.body.style.backgroundColor = 'green';";
options.Start.SetStartAfterScriptRun(js);

var url = new Uri("https://google.com");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

以上代码片段仅用于演示方法,非常简单。如需查看更实际的示例,请访问我们 GitHub 代码库中的相应示例应用。该应用演示了如何处理动态加载内容的页面。应用中的 JavaScript 代码会滚动页面,直到没有新内容为止。之后,即可进行 PDF 转换。

在 .NET 中将 HTML 转换为 PDF,忽略 SSL 错误

当发送安全请求加载 HTML 时,该插件会检查用于验证网站身份并启用加密连接的 SSL 证书是否有效且可信。

默认情况下,如果 HTML 转 PDF 转换器出于任何原因不信任该证书,插件将抛出异常。这种情况通常是由于证书是自签名证书、已吊销证书或已过期证书造成的。

如果您了解接受不受信任的证书的风险,可以使用引擎选项指示插件绕过这些检查。

var engineOptions = new HtmlEngineOptions
{
    IgnoreSslErrors = true
};
using var converter = await HtmlConverter.CreateAsync(engineOptions);

var url = new Uri("https://self-signed.badssl.com/");
using var pdf = await converter.CreatePdfAsync(url);
pdf.Save("output.pdf");

完整代码请前往 Docotic.Pdf 示例仓库。

在现有 PDF 上叠加 HTML 代码

有时,您可能希望使用现有的 PDF 文件作为转换结果的背景。例如,当您有一张表单图片,并希望在图片中的空白区域添加内容时,最终效果看起来就像填写好的表单。Docotic.Pdf 及其插件可以实现这一点。

此过程包括从 HTML(叠加内容)创建一个新的 PDF 文件,然后将其与现有 PDF 文件合并。最终文档将同时包含原始内容和新的叠加内容。以下代码演示了此过程。

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
options.Page.SetSizeInches(4.13, 5.83);

string htmlCode =
    "<div style=\"position: absolute; top: 270px; right: 100px;\">" +
    "I would like to put this here</div>";
using var htmlPdf = await converter.CreatePdfFromStringAsync(htmlCode, options);

using var pdf = new PdfDocument("pdf-to-merge-with.pdf");
var xObj = pdf.CreateXObject(htmlPdf.Pages[0]);

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

指定叠加层的页面大小非常重要。通常,叠加层的大小应与您要叠加的页面大小相同。然后,​​您需要生成包含叠加内容的新 PDF 文件。请注意,默认情况下背景是透明的。如有需要,您可以在转换之前运行脚本来更改背景。

以上代码:

  • 根据 HTML 创建一个带有透明页面的 PDF 文档
  • 打开一个现有的 PDF 文件
  • 根据转换后的文档的第一页在现有文档中创建一个 XObject
  • 将该 XObject 绘制到现有文档的第一页上

完整的带有示例源 PDF 的测试项目位于 Docotic.Pdf 示例存储库中。