IronPDF 2021:Chrome渲染引擎EAP – PDF生成的变革者!
DinkToPdf 封装了 wkhtmltopdf,继承了其所有的安全漏洞和技术限制。 了解这些问题对于评估迁移的紧迫性至关重要。
关键安全问题
DinkToPdf 从 wkhtmltopdf 继承未修补的安全公告:
- CVE-2022-35583 (SSRF): 针对 wkhtmltopdf 0.12.6 的一项服务器端请求伪造公告(CVSS 9.8 在 NVD; 被上游项目认为是应用侧输入清理问题而非库缺陷)。 无论怎样,该问题将不会被修补。
- 归档项目:
wkhtmltopdf/wkhtmltopdf仓库于2023年1月2日归档,整个wkhtmltopdfGitHub 组织于2024年7月10日归档。 - 无未来安全补丁: 所有已知或未来的漏洞将不上游修复。
技术问题
| 问题 | 影响 |
|---|---|
| 线程安全 | BasicConverter 仅支持单线程; SynchronizedConverter 序列化调用,并且在负载下可能仍然导致本地端崩溃 |
| 本地二进制文件 | 复杂部署与平台特定的 libwkhtmltox 二进制文件 |
| CSS限制 | 旧的 QtWebKit 叉——不支持现代Flexbox/Grid布局 |
| JavaScript语言 | 执行不一致、超时 |
| 渲染 | 过时的基于 QtWebKit 的引擎(wkhtmltopdf 0.12.6,最后发布于 2020 年 6 月) |
| 维护 | DinkToPdf 1.0.8 最后版本发布于 2017年4月18日 在 NuGet |
架构比较
| 方面 | DinkToPdf | IronPDF |
|---|---|---|
| 安全性 | CVE-2022-35583 (SSRF),未修补 / 上游有争议 | 没有已知的关键CVE |
| 渲染引擎 | 旧的 QtWebKit 分支 (wkhtmltopdf 0.12.6) | 现代 Chromium |
| 线程安全 | SynchronizedConverter 序列化调用; native-side crashes reported under load |
线程安全设计 |
| 本地依赖关系 | 平台特定的 libwkhtmltox 二进制文件 |
已管理的NuGet包 |
| CSS支持 | 没有现代Flexbox/Grid | 完整的 CSS3 |
| JavaScript语言 | 有限、不一致 | 支持 |
| 维护 | DinkToPdf 最后版本发布于 2017年4月 wkhtmltopdf 组织于 2024年7月 归档 | 积极维护 |
功能对比
| 特征 | DinkToPdf | IronPDF |
|---|---|---|
| HTML 至 PDF | ✅(过时的引擎) | ✅(Chromium) |
| URL 至 PDF | ✅ | ✅ |
| 自定义页边距 | ✅ | ✅ |
| 页眉/页脚 | ✅(有限) | ✅ (完整 HTML) |
| CSS3 | ❌ 有限公司 | ✅ 全文 |
| Flexbox/Grid | ❌ | ✅ |
| JavaScript | ⚠ 限制 | ✅ 全文 |
| PDF 操作 | ❌ | ✅ |
| 表格填写 | ❌ | ✅ |
| 数字签名 | ❌ | ✅ |
| 加密 | ❌ | ✅ |
| 水印 | ❌ | ✅ |
| 合并/拆分 | ❌ | ✅ |
迁移前准备
前提条件
确保您的环境符合这些要求:
- .NET Framework 4.6.2+, .NET Core 3.1+, or .NET 5/6/7/8/9/10
- Visual Studio 2019+ 或带有 C# 扩展的 VS Code
- 访问 NuGet 包管理器 -IronPDF许可证密钥(可在ironpdf.com免费试用)
审核DinkToPdf的使用情况
在您的解决方案目录中运行这些命令,以识别所有DinkToPdf引用:
# Find allDinkToPdfusages in your codebase
grep -r "using DinkToPdf" --include="*.cs" .
grep -r "SynchronizedConverter\|HtmlToPdfDocument\|ObjectSettings" --include="*.cs" .
# Find NuGet package references
grep -r "DinkToPdf" --include="*.csproj" .
# Find wkhtmltopdf binaries
find . -name "libwkhtmltox*"
# Find allDinkToPdfusages in your codebase
grep -r "using DinkToPdf" --include="*.cs" .
grep -r "SynchronizedConverter\|HtmlToPdfDocument\|ObjectSettings" --include="*.cs" .
# Find NuGet package references
grep -r "DinkToPdf" --include="*.csproj" .
# Find wkhtmltopdf binaries
find . -name "libwkhtmltox*"
值得期待的重大变化
| 变更 | DinkToPdf | IronPDF | 影响 |
|---|---|---|---|
| 转换器 | SynchronizedConverter(new PdfTools()) |
ChromePdfRenderer |
更简单的实例化 |
| 文档 | HtmlToPdfDocument |
直接方法调用 | 无文档对象 |
| 设置 | GlobalSettings + ObjectSettings |
RenderingOptions |
单一选项对象 |
| 返回类型 | byte[] |
PdfDocument |
更强大的对象 |
| 二进制 | libwkhtmltox.dll/so |
无(托管) | 删除本地文件 |
| 线程安全 | BasicConverter 单线程; SynchronizedConverter 序列化 |
默认为线程安全 | 简化代码 |
| DI | 需要单例 | 终生 | 灵活 |
逐步迁移过程
步骤 1:更新 NuGet 软件包
移除DinkToPdf并安装 IronPDF:
# Remove DinkToPdf
dotnet remove package DinkToPdf
# Install IronPDF
dotnet add package IronPdf
# Remove DinkToPdf
dotnet remove package DinkToPdf
# Install IronPDF
dotnet add package IronPdf
步骤 2:删除本地二进制文件
从您的项目中删除这些特定于平台的文件:
libwkhtmltox.dll(Windows)libwkhtmltox.so(Linux)libwkhtmltox.dylib(macOS)
IronPDF 没有本地依赖性--一切都是托管代码。
步骤 3:更新命名空间引用
用IronPDF替换DinkToPdf命名空间:
// Remove these
using DinkToPdf;
using DinkToPdf.Contracts;
// Add this
using IronPdf;
// Remove these
using DinkToPdf;
using DinkToPdf.Contracts;
// Add this
using IronPdf;
Imports IronPdf
步骤 4:配置许可证
// Add at application startup (Program.cs or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
完整的 API 迁移参考
核心类映射
| DinkToPdf | IronPDF |
|---|---|
SynchronizedConverter |
ChromePdfRenderer |
BasicConverter |
ChromePdfRenderer |
PdfTools |
不需要 |
HtmlToPdfDocument |
不需要 |
GlobalSettings |
RenderingOptions |
ObjectSettings |
RenderingOptions |
MarginSettings |
个别边距属性 |
全局设置映射
| DinkToPdf 全局设置 | IronPDF 同等产品 |
|---|---|
ColorMode = ColorMode.Color |
默认(始终为彩色) |
Orientation = Orientation.Portrait |
PaperOrientation = PdfPaperOrientation.Portrait |
Orientation = Orientation.Landscape |
PaperOrientation = PdfPaperOrientation.Landscape |
PaperSize = PaperKind.A4 |
PaperSize = PdfPaperSize.A4 |
Margins = new MarginSettings() |
个别边距属性 |
边距设置映射
| DinkToPdf 边界 | IronPDF 同等产品 |
|---|---|
Margins.Top = 10 |
MarginTop = 10 |
Margins.Bottom = 10 |
MarginBottom = 10 |
Margins.Left = 15 |
MarginLeft = 15 |
Margins.Right = 15 |
MarginRight = 15 |
代码迁移示例
将基本 HTML 转换为 PDF.
基本转换演示了从DinkToPdf的冗长配置到IronPDF的精简 API 的巨大简化。
DinkToPdf实现:
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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>",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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>",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}
Imports DinkToPdf
Imports DinkToPdf.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.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = {
New ObjectSettings() With {
.HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>",
.WebSettings = New WebSettings() With {
.DefaultEncoding = "utf-8"
}
}
}
}
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
IronPDF 可将 20 行的DinkToPdf配置缩减为 4 行。 没有 SynchronizedConverter,没有 PdfTools,没有 HtmlToPdfDocument,没有 ObjectSettings——只需渲染并保存。 有关更多选项,请参阅 HTML 转 PDF 文档。
URL到PDF转换
DinkToPdf实现:
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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 DinkToPdf
using DinkToPdf;
using DinkToPdf.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 DinkToPdf
Imports DinkToPdf.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.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
IronPDF 的 RenderUrlAsPdf 用直接的方法调用替换了嵌套的 ObjectSettings.Page 配置。 有关更多选项,请参阅 URL to PDF 文档。
横向和页边距自定义设置
DinkToPdf实现:
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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 = 15, Right = 15 }
},
Objects = {
new ObjectSettings() {
HtmlContent = "<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("custom.pdf", pdf);
}
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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 = 15, Right = 15 }
},
Objects = {
new ObjectSettings() {
HtmlContent = "<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("custom.pdf", pdf);
}
}
Imports DinkToPdf
Imports DinkToPdf.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 = 15,
.Right = 15
}
},
.Objects = {
New ObjectSettings() With {
.HtmlContent = "<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>",
.WebSettings = New WebSettings() With {
.DefaultEncoding = "utf-8"
}
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("custom.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 = 15;
renderer.RenderingOptions.MarginRight = 15;
var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>");
pdf.SaveAs("custom.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 = 15;
renderer.RenderingOptions.MarginRight = 15;
var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>");
pdf.SaveAs("custom.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Module Program
Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
renderer.RenderingOptions.MarginTop = 10
renderer.RenderingOptions.MarginBottom = 10
renderer.RenderingOptions.MarginLeft = 15
renderer.RenderingOptions.MarginRight = 15
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>")
pdf.SaveAs("custom.pdf")
End Sub
End Module
IronPDF 的 RenderingOptions 用统一的、流畅的 API 替代了 GlobalSettings 和 MarginSettings。 有关更多配置选项,请参阅渲染选项文档。
关键迁移说明
删除本地二进制文件
最重要的清理步骤是删除 wkhtmltopdf 本机二进制文件。IronPDF没有本地依赖性:
# Delete native binaries
rm libwkhtmltox.* 2>/dev/null
# Delete native binaries
rm libwkhtmltox.* 2>/dev/null
无需单例
DinkToPdf 的文档指导是将 SynchronizedConverter 注册为单例。IronPDF的 ChromePdfRenderer 在任何 DI 生命周期内都是线程安全的:
//DinkToPdf- typically registered as singleton
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
//IronPDF- any lifetime works
services.AddScoped<ChromePdfRenderer>();
// Or just create inline:
var renderer = new ChromePdfRenderer();
//DinkToPdf- typically registered as singleton
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
//IronPDF- any lifetime works
services.AddScoped<ChromePdfRenderer>();
// Or just create inline:
var renderer = new ChromePdfRenderer();
' DinkToPdf - typically registered as singleton
services.AddSingleton(GetType(IConverter), New SynchronizedConverter(New PdfTools()))
' IronPDF - any lifetime works
services.AddScoped(Of ChromePdfRenderer)()
' Or just create inline:
Dim renderer As New ChromePdfRenderer()
Richer 返回类型
DinkToPdf 返回 byte[]。IronPDF返回具有操作能力的 PdfDocument:
//DinkToPdfreturns byte[]
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
return File(pdf, "application/pdf");
//IronPDFreturns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
return File(pdf.BinaryData, "application/pdf");
//DinkToPdfreturns byte[]
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
return File(pdf, "application/pdf");
//IronPDFreturns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
return File(pdf.BinaryData, "application/pdf");
' DinkToPdf returns byte()
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("output.pdf", pdf)
Return File(pdf, "application/pdf")
' IronPDF returns PdfDocument
Dim pdfDocument = renderer.RenderHtmlAsPdf(html)
pdfDocument.SaveAs("output.pdf")
Return File(pdfDocument.BinaryData, "application/pdf")
完全支持 CSS3.
在DinkToPdf中失效的现代布局在IronPDF中可以完美运行:
//DinkToPdf- doesn't work (wkhtmltopdf uses 2015 WebKit)
var html = "<div style='display: flex;'>...</div>"; // Broken!
//IronPDF- full support (modern Chromium)
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html); // Works!
//DinkToPdf- doesn't work (wkhtmltopdf uses 2015 WebKit)
var html = "<div style='display: flex;'>...</div>"; // Broken!
//IronPDF- full support (modern Chromium)
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html); // Works!
' DinkToPdf- doesn't work (wkhtmltopdf uses 2015 WebKit)
Dim html As String = "<div style='display: flex;'>...</div>" ' Broken!
' IronPDF- full support (modern Chromium)
Dim html As String = "
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>"
Dim pdf = renderer.RenderHtmlAsPdf(html) ' Works!
迁移后核对表
完成代码迁移后,请验证以下内容:
运行所有单元测试以验证 PDF 生成功能是否正常。
- 测试多线程场景(
SynchronizedConverter路径序列化调用,并且在负载下容易发生本地端崩溃) - 对比PDF输出质量(IronPDF的Chromium渲染效果更好)
- 验证 CSS 渲染效果(Flexbox/Grid 现在正常工作)
- 测试JavaScript执行(使用IronPDF可确保可靠性)
- 更新 CI/CD 流水线,移除 wkhtmltopdf 安装
- 验证安全扫描通过(不再有 CVE-2022-35583 标志)
- 从 Docker/部署脚本中移除原生二进制部署
其他资源
从DinkToPdf迁移到IronPDF解除了未打补丁的 wkhtmltopdf 攻击面 (CVE-2022-35583)、序列化的 SynchronizedConverter 并发模型、本地二进制部署和较旧的 QtWebKit 渲染路径。 过渡到现代的 Chromium 引擎提供了完整的CSS3支持、可靠的JavaScript执行以及一个被积极维护的库。

