如何在 C# | IronPDF 中添加目录
wkhtmltopdf是一个被广泛使用的工具,用于将HTML文档转换为PDF,使用的是Qt 4.8 + QtWebKit。 尽管该项目因其命令行功能和免费许可而深受开发人员的欢迎,但它现在存在的严重安全风险已不容忽视。 GitHub存储库已于2023年1月2日归档; 最后的上游版本是2020年6月11日的0.12.6; 并且CVE-2022-35583(CVSS 9.8,SSRF)仍未修补。
本指南提供了从 wkhtmltopdf 到IronPDF的完整迁移路径,为需要从应用程序中消除这种安全风险的专业 .NET 开发人员提供了分步指导、代码比较和实用示例。
关键安全警告:CVE-2022-35583
wkhtmltopdf 包含一个永远无法修复的重要安全漏洞:
| 问题 | 详细信息 | 现状 |
|---|---|---|
| CVE-2022-35583(SSRF,CWE-918) | 关键(CVSS 9.8) | 未修补 - 维护者提出异议 |
| GitHub存储库已归档 | 只读 | 2023年1月2日 |
| 最后的上游版本 | 0.12.6 | 2020年6月11日 |
| 底层引擎 | Qt 4.8 + QtWebKit(Qt 4.8 于2015年终止支持) | 已关闭 |
| CSS 网格支持 | None | 破译 |
| Flexbox 支持 | 部分翻译 | 破译 |
| ES6+JavaScript> | 有限的 | 破译 |
SSRF 攻击如何工作
服务器端请求伪造漏洞允许攻击者访问内部服务、窃取凭证、扫描您的内部网络并通过伪造的 HTML 外泄敏感数据:
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>
当 wkhtmltopdf 渲染 HTML 时,它会绕过防火墙和安全控制,从服务器的网络上下文中获取这些 URL。
受影响的封装库
每个.NET包装器都绑定或外壳使用相同的wkhtmltopdf本地二进制,所以它们无论包装器本身多活跃,都会继承其CVE漏洞:
| 封装库 | 最新的NuGet | 安全风险 |
|---|---|---|
| DinkToPdf | 1.0.8(2017年4月) - 被遗弃 | 继承CVE-2022-35583 |
| Rotativa.AspNetCore(webgio的分支) | 1.4.0(2023年11月) - 包装器更新,二进制冻结 | 继承CVE-2022-35583 |
| TuesPechkin | 2.1.1(2015年1月) - 被遗弃 | 继承CVE-2022-35583 |
Haukcode.WkHtmlToPdfDotNet (formerly WkHtmlToPdf-DotNet) |
1.5.95(2024年10月) - 包装器更新,二进制冻结 | 继承CVE-2022-35583 |
| NReco.PdfGenerator | 包装器更新,绑定wkhtmltopdf | 继承CVE-2022-35583 |
如果您使用这些库中的任何一个,除非您清洗所有HTML输入,否则您的应用程序会暴露于CVE-2022-35583。
IronPDF与 wkhtmltopdf:功能对比
了解架构差异有助于技术决策者评估迁移投资:
| 特征 | wkhtmltopdf | IronPDF |
|---|---|---|
| 许可 | LGPLv3 (免费) | 商业翻译 |
| 渲染引擎 | Qt 4.8 + QtWebKit(Qt 4.8 于2015年终止支持) | 当前Chromium引擎 |
| 安全漏洞 | CVE-2022-35583(CVSS 9.8)未修补,存有争议 | 未报告严重的CVE |
| 主动维护 | GitHub存储库已于2023年1月2日归档; 最后的版本于2020年6月 | 定期发布,积极维护 |
| 支持现代网络标准 | 有限(flexbox 已损坏,无 CSS 网格) | 支持 |
| 集成与支持 | 仅限于社区论坛 | 广泛的文档和专门的支持 |
| CSS 网格 | ❌ 不支持 | ✅ 已支持 |
| Flexbox | ⚠ 损坏 | ✅ 已支持 |
| ES6+JavaScript> | ❌ 不支持 | ✅ 已支持 |
| 同步/等待 | ❌ 不支持 | ✅ 已支持 |
| PDF 操作 | ❌ 不支持 | ✅ 已支持 |
| 数字签名 | ❌ 不支持 | ✅ 已支持 |
| PDF/A合规性 | ❌ 不支持 | ✅ 已支持 |
快速入门:wkhtmltopdf 到IronPDF的迁移
迁移工作可以通过以下基本步骤立即开始。
步骤 1:删除 wkhtmltopdf 软件包和二进制文件
删除所有 wkhtmltopdf 封装包:
# Remove wkhtmltopdf wrapper (whichever you're using)
dotnet remove package Haukcode.WkHtmlToPdfDotNet
dotnet remove package DinkToPdf
dotnet remove package TuesPechkin
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
dotnet remove package NReco.PdfGenerator
# Remove wkhtmltopdf binary from your deployment
# Delete wkhtmltopdf.exe, wkhtmltox.dll, etc.
# Remove wkhtmltopdf wrapper (whichever you're using)
dotnet remove package Haukcode.WkHtmlToPdfDotNet
dotnet remove package DinkToPdf
dotnet remove package TuesPechkin
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
dotnet remove package NReco.PdfGenerator
# Remove wkhtmltopdf binary from your deployment
# Delete wkhtmltopdf.exe, wkhtmltox.dll, etc.
步骤2:安装IronPDF
# AddIronPDF(secure, modern alternative)
dotnet add package IronPdf
# AddIronPDF(secure, modern alternative)
dotnet add package IronPdf
步骤 3:更新命名空间
将wkhtmltopdf命名空间替换为IronPDF命名空间:
// Before (wkhtmltopdf)
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
// After (IronPDF)
using IronPdf;
// Before (wkhtmltopdf)
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
// After (IronPDF)
using IronPdf;
Imports IronPdf
步骤 4:初始化许可证
在应用程序启动时添加许可证初始化:
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
代码迁移示例
将HTML转换为PDF
最基本的操作揭示了这些 .NET PDF 方法之间的复杂性差异。
wkhtmltopdf 方法:
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.WkHtmlToPdfDotNet.Contracts
Imports System.IO
Module Program
Sub Main()
Dim converter As New SynchronizedConverter(New PdfTools())
Dim doc As New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = New List(Of ObjectSettings) From {
New ObjectSettings() With {
.HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("output.pdf", pdf)
End Sub
End Module
IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>")
pdf.SaveAs("output.pdf")
End Sub
End Class
wkhtmltopdf 需要创建一个 SynchronizedConverter 使用 PdfTools,构造一个 HtmlToPdfDocument 使用 GlobalSettings 和 Objects,设置属性比如 ColorMode, Orientation 和 PaperSize,调用 converter.Convert() 获取原始字节,并手动使用 File.WriteAllBytes() 写入文件。
IronPDF 完全消除了这种繁琐过程——创建一个 ChromePdfRenderer,调用 RenderHtmlAsPdf(),使用内置的 SaveAs() 方法。
有关 HTML 转 PDF 的高级应用场景,请参阅 HTML 转 PDF 指南。
将 URL 转换为 PDF
URL 到 PDF 的转换显示出类似的复杂性模式。
wkhtmltopdf 方法:
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
Page = "https://www.example.com"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("webpage.pdf", pdf);
}
}
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
Page = "https://www.example.com"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("webpage.pdf", pdf);
}
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.WkHtmlToPdfDotNet.Contracts
Imports System.IO
Module Program
Sub Main()
Dim converter As New SynchronizedConverter(New PdfTools())
Dim doc As New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = New List(Of ObjectSettings) From {
New ObjectSettings() With {
.Page = "https://www.example.com"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("webpage.pdf", pdf)
End Sub
End Module
IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
wkhtmltopdf 使用 Page 属性在 ObjectSettings 中指定一个 URL,需要相同的文档构造模式。IronPDF提供一个专用的 RenderUrlAsPdf() 方法,清楚地表达意图。
请浏览 URL to PDF 文档,了解身份验证和自定义页眉选项。
自定义设置:带有页面配置的 HTML 文件
配置方向、页边距和纸张大小需要采用不同的方法。
wkhtmltopdf 方法:
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Landscape,
PaperSize = PaperKind.A4,
Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
},
Objects = {
new ObjectSettings()
{
Page = "input.html",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("custom-output.pdf", pdf);
}
}
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Landscape,
PaperSize = PaperKind.A4,
Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
},
Objects = {
new ObjectSettings()
{
Page = "input.html",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("custom-output.pdf", pdf);
}
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.WkHtmlToPdfDotNet.Contracts
Imports System.IO
Module Program
Sub Main()
Dim converter = New SynchronizedConverter(New PdfTools())
Dim doc = New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Landscape,
.PaperSize = PaperKind.A4,
.Margins = New MarginSettings() With {.Top = 10, .Bottom = 10, .Left = 10, .Right = 10}
},
.Objects = {
New ObjectSettings() With {
.Page = "input.html",
.WebSettings = New WebSettings() With {.DefaultEncoding = "utf-8"}
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("custom-output.pdf", pdf)
End Sub
End Module
IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("custom-output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("custom-output.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Class Program
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
renderer.RenderingOptions.MarginTop = 10
renderer.RenderingOptions.MarginBottom = 10
renderer.RenderingOptions.MarginLeft = 10
renderer.RenderingOptions.MarginRight = 10
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
pdf.SaveAs("custom-output.pdf")
End Sub
End Class
wkhtmltopdf 在 GlobalSettings 和 Objects 中嵌套设置,MarginSettings 作为一个独立的对象。IronPDF提供直接的 RenderingOptions 属性,名称清晰如 PaperOrientation, MarginTop 和 PaperSize。
wkhtmltopdf API 到IronPDF映射参考
这种映射通过显示直接的 API 对应关系来加速迁移:
CLI 到IronPDF的映射
| wkhtmltopdf CLI 选项 | IronPDF 同等产品 |
|---|---|
wkhtmltopdf input.html output.pdf |
renderer.RenderHtmlFileAsPdf() |
wkhtmltopdf URL output.pdf |
renderer.RenderUrlAsPdf() |
--page-size A4 |
RenderingOptions.PaperSize = PdfPaperSize.A4 |
--page-size Letter |
RenderingOptions.PaperSize = PdfPaperSize.Letter |
--orientation Landscape |
RenderingOptions.PaperOrientation = Landscape |
--margin-top 10mm |
RenderingOptions.MarginTop = 10 |
--margin-bottom 10mm |
RenderingOptions.MarginBottom = 10 |
--margin-left 10mm |
RenderingOptions.MarginLeft = 10 |
--margin-right 10mm |
RenderingOptions.MarginRight = 10 |
--header-html header.html |
RenderingOptions.HtmlHeader |
--footer-center "[page]" |
{page} placeholder |
--footer-center "[toPage]" |
{total-pages} placeholder |
--enable-javascript |
默认已启用 |
--javascript-delay 500 |
RenderingOptions.WaitFor.RenderDelay = 500 |
--dpi 300 |
RenderingOptions.Dpi = 300 |
--grayscale |
RenderingOptions.GrayScale = true |
C#包装API映射
| wkhtmltopdf 封装程序 | IronPDF |
|---|---|
SynchronizedConverter |
ChromePdfRenderer |
HtmlToPdfDocument |
RenderingOptions |
GlobalSettings.Out |
pdf.SaveAs() |
GlobalSettings.PaperSize |
RenderingOptions.PaperSize |
GlobalSettings.Orientation |
RenderingOptions.PaperOrientation |
GlobalSettings.Margins |
RenderingOptions.Margin* |
ObjectSettings.Page |
RenderHtmlFileAsPdf() |
ObjectSettings.HtmlContent |
RenderHtmlAsPdf() |
converter.Convert(doc) |
renderer.RenderHtmlAsPdf() |
占位符语法迁移
| wkhtmltopdf 占位符 | IronPDF 占位符 |
|---|---|
[page] |
{page} |
[toPage] |
{total-pages} |
[date] |
{date} |
[time] |
{time} |
[title] |
{html-title} |
[url] |
{url} |
常见迁移问题和解决方案
问题 1:页眉/页脚占位符语法
wkhtmltopdf: 使用方括号语法如 [page] 和 [toPage]。
解决方案:更新IronPDF的大括号占位符:
// Before (wkhtmltopdf)
FooterSettings = { Left = "Page [page] of [toPage]" }
// After (IronPDF)
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align:left;'>Page {page} of {total-pages}</div>",
MaxHeight = 25
};
// Before (wkhtmltopdf)
FooterSettings = { Left = "Page [page] of [toPage]" }
// After (IronPDF)
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align:left;'>Page {page} of {total-pages}</div>",
MaxHeight = 25
};
' Before (wkhtmltopdf)
FooterSettings = New With {.Left = "Page [page] of [toPage]"}
' After (IronPDF)
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.HtmlFragment = "<div style='text-align:left;'>Page {page} of {total-pages}</div>",
.MaxHeight = 25
}
问题 2:JavaScript 延迟配置
wkhtmltopdf: 使用 JavaScriptDelay 属性,可靠性有限。
解决方案:IronPDF提供多种选择:
renderer.RenderingOptions.EnableJavaScript = true;
// Option 1: Fixed delay
renderer.RenderingOptions.WaitFor.RenderDelay(500);
// Option 2: Wait for specific element (more reliable)
renderer.RenderingOptions.WaitFor.HtmlElementById("content-loaded");
// Option 3: Wait for JavaScript condition
renderer.RenderingOptions.WaitFor.JavaScript("window.renderComplete === true");
renderer.RenderingOptions.EnableJavaScript = true;
// Option 1: Fixed delay
renderer.RenderingOptions.WaitFor.RenderDelay(500);
// Option 2: Wait for specific element (more reliable)
renderer.RenderingOptions.WaitFor.HtmlElementById("content-loaded");
// Option 3: Wait for JavaScript condition
renderer.RenderingOptions.WaitFor.JavaScript("window.renderComplete === true");
renderer.RenderingOptions.EnableJavaScript = True
' Option 1: Fixed delay
renderer.RenderingOptions.WaitFor.RenderDelay(500)
' Option 2: Wait for specific element (more reliable)
renderer.RenderingOptions.WaitFor.HtmlElementById("content-loaded")
' Option 3: Wait for JavaScript condition
renderer.RenderingOptions.WaitFor.JavaScript("window.renderComplete === true")
问题 3:现代 CSS 无法渲染
症状: CSS 网格和 Flexbox 布局在 wkhtmltopdf 中呈现不正确。
解决方案:IronPDF的 Chromium 引擎可正确处理现代 CSS:
// This CSS now works with IronPDF
var html = @"
<style>
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.flex { display: flex; justify-content: space-between; align-items: center; }
</style>
<div class='grid'>
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html);
// This CSS now works with IronPDF
var html = @"
<style>
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.flex { display: flex; justify-content: space-between; align-items: center; }
</style>
<div class='grid'>
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html);
Dim html As String = "
<style>
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.flex { display: flex; justify-content: space-between; align-items: center; }
</style>
<div class='grid'>
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</div>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
第 4 期:同步与异步渲染
wkhtmltopdf:封装器是同步和阻塞线程。
解决方案:IronPDF支持异步渲染:
public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
Imports System.Threading.Tasks
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Dim renderer As New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Function
wkhtmltopdf迁移清单
迁移前任务
审核您的代码库,确定所有 wkhtmltopdf 的使用情况:
# Find all wkhtmltopdf references
grep -r "Haukcode.WkHtmlToPdfDotNet\|WkHtmlToPdfDotNet\|DinkToPdf\|TuesPechkin\|Rotativa\|NReco.PdfGenerator" --include="*.cs" .
grep -r "wkhtmltopdf" --include="*.yml" --include="*.yaml" --include="Dockerfile" .
# Find all wkhtmltopdf references
grep -r "Haukcode.WkHtmlToPdfDotNet\|WkHtmlToPdfDotNet\|DinkToPdf\|TuesPechkin\|Rotativa\|NReco.PdfGenerator" --include="*.cs" .
grep -r "wkhtmltopdf" --include="*.yml" --include="*.yaml" --include="Dockerfile" .
查找并记录 wkhtmltopdf 二进制文件,以便删除。 文档当前设置(纸张大小、页边距、页眉/页脚)。
代码更新任务
1.删除所有 wkhtmltopdf 封装 NuGet 软件包 2.删除 wkhtmltopdf 二进制文件(wkhtmltopdf.exe、wkhtmltox.dll)
- 安装IronPDF NuGet包
- 更新命名空间导入,从
Haukcode.WkHtmlToPdfDotNet(或您使用的包装器) 到IronPdf - 用
ChromePdfRenderer替换SynchronizedConverter - 将
HtmlToPdfDocument模式转换为直接渲染方法 - 更新
GlobalSettings配置为RenderingOptions - 将边距配置从
MarginSettings转换为独立属性 - 更新占位符语法 (
[page]→{page},[toPage]→{total-pages}) 10.在启动时添加IronPDF许可证初始化功能
迁移后测试
迁移后,验证这些方面:
- PDF 输出的可视化比较(应通过现代 CSS 支持加以改进)
- 验证现代 CSS 渲染(CSS 栅格和 Flexbox 现在可以使用)
- 测试 JavaScript 较多的页面
- 安全扫描以确认没有 wkhtmltopdf 二进制文件残留
- 性能比较负载测试
安全验证
# Scan for any remaining wkhtmltopdf artifacts
find /var/www/ -name "*wkhtmlto*" 2>/dev/null
find /usr/local/bin/ -name "*wkhtmlto*" 2>/dev/null
docker images | grep wkhtmltopdf
# Check if any process is still using it
ps aux | grep wkhtmltopdf
# Scan for any remaining wkhtmltopdf artifacts
find /var/www/ -name "*wkhtmlto*" 2>/dev/null
find /usr/local/bin/ -name "*wkhtmlto*" 2>/dev/null
docker images | grep wkhtmltopdf
# Check if any process is still using it
ps aux | grep wkhtmltopdf
迁移到IronPDF的主要优势
从 wkhtmltopdf 迁移到IronPDF有几个关键优势:
安全性: CVE-2022-35583 和所有 wkhtmltopdf 漏洞均已消除。IronPDF没有已知的 CVE,并定期接受安全更新。
现代渲染引擎:IronPDF使用最新的 Chromium 引擎,确保完全支持 CSS3、CSS Grid、Flexbox 和 ES6+ JavaScript。 正确呈现现代框架。
简化 API:直接渲染方法取代文档构造模式。 内置 SaveAs() 方法消除了手动字节处理。
扩展功能: PDF 操作、数字签名、PDF/A 合规性、水印和合并/拆分操作是 wkhtmltopdf 无法提供的内置功能。
积极开发:IronPDF的定期更新跟踪当前的.NET发布,因此支持现代的.NET和C#语言版本。
异步支持:通过原生 async/await 支持,防止高负载 Web 应用程序中的线程阻塞。

