该页面可以包含自动翻译的文本。
在 C# 和 VB.NET 中将 HTML 转换为 PDF
如果你已经在以 HTML 形式创建内容上投入了大量时间和资金,那么你可能希望直接从该 HTML 创建 PDF。对于想避免重复工作的任何人来说,这种方法都是自然选择。
本文详细介绍如何在 .NET 中使用 Docotic.Pdf 及其免费的 HtmlToPdf 加载项将 HTML 转换为 PDF。
有关为什么 Docotic.Pdf 是正确选择、如何安装加载项以及转换在内部如何工作的信息,请参阅 HTML 转 PDF API 概览 页面。

简单的 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# 且没有 async 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 版本。
使用 HTML 字符串或文件在 C# 和 VB.NET 中创建 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 模板创建这些块。我们建议在模板内的图像上使用内联样式和 Data 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 代码,并支持少量变量。这些变量是 date、title、url、pageNumber 和 totalPages。 页眉模板 和 页脚模板 都支持同一组变量。
完整的 测试项目和模板代码 位于 Docotic.Pdf 示例仓库中。示例代码展示了如何在模板中使用这些变量和 Data 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 提供了在转换前运行 JS 代码的方法。代码可以动态生成或修改 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 示例仓库。
将 HTML 覆盖到现有 PDF 上
有时你可能希望将现有 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 示例仓库中。