TuesPechkin 与 IronPDF:技术比较指南
当.NET 开发人员需要将 HTML 转换为 PDF 时,有几个围绕传统渲染引擎构建的封装库可供选择。TuesPechkin就是这样一种解决方案,它封装了 wkhtmltopdf 库,提供 PDF 生成功能。 本技术比较将研究TuesPechkin和 IronPDF,以帮助架构师和开发人员了解传统封装器和现代 PDF 库之间的权衡。
了解 TuesPechkin
TuesPechkin 是 wkhtmltopdf 库的线程安全封装程序,旨在帮助开发人员从 HTML 内容生成 PDF 文档。 该库通过提供ThreadSafeConverter实现来应对wkhtmltopdf固有的并发挑战。
但TuesPechkin继承了其底层技术的基本局限性:
-已弃用的基金会:TuesPechkin为 wkhtmltopdf 提供转载服务,该项目上次更新于 2015 年,并于 2022 年 12 月正式弃用。 -渲染引擎过时:使用 Qt WebKit 4.8,这是 Chrome 时代之前的渲染引擎。
- 复杂线程管理:需要开发人员通过
RemotingToolset和部署模式手动配置线程安全 - 负载下的稳定性:即使配置了线程安全,库在高并发时可能会因
AccessViolationException或进程挂起而崩溃 - CSS 支持有限:不支持 Flexbox 或 CSS Grid 等现代 CSS 特性。
- JavaScript 的局限性: JavaScript 执行不稳定,不支持 ES6+。
安全考虑因素
TuesPechkin 继承了 wkhtmltopdf 的所有安全漏洞。 CVE-2022-35583 被评为 "严重"(9.8/10),是一个影响所有TuesPechkin版本的服务器端请求伪造漏洞。 由于 wkhtmltopdf 已被弃用,此漏洞将永远不会被修补,这意味着使用TuesPechkin的应用程序将永远暴露在漏洞中。
了解IronPDF
IronPDF 采用了一种根本不同的方法,它提供了一个具有本地线程安全和基于 Chromium 的渲染引擎的现代商用 PDF 库。IronPDF 并未对传统工具进行封装,而是将 PDF 生成作为其主要重点。
IronPDF的主要特点包括:
-现代 Chromium 引擎:支持 HTML5、CSS3、Flexbox、CSS Grid 和 ES6+ JavaScript -原生线程安全:无需手动线程管理——并发操作自动运行 -积极开发:每周更新和持续改进 -全面的 PDF 功能:除了生成 PDF 之外,还包括编辑、数字签名、PDF/A 合规性和表单填写。 -集成简便:无需原生二进制部署,即可通过 NuGet 直接安装
功能对比
下表重点介绍了TuesPechkin和IronPDF之间的技术差异:
| 特征 | TuesPechkin | IronPDF |
|---|---|---|
| 许可 | 免费(MIT 许可) | 商业翻译 |
| 线程安全 | 需要人工管理 | 本地支持 |
| 货币 | 有局限性,在负载情况下可能会崩溃 | 稳健,可处理高并发 |
| 开发状态 | 不活跃,最后更新时间为 2015 年 | 积极、持续的改进 |
| 易用性 | 复杂的设置 | 方便用户使用的指南 |
| 文档 | 基本的 | 包含大量示例 |
| 渲染引擎 | Qt WebKit 4.8(已过时) | 现代 Chromium |
| CSS3 支持。 | 部分翻译 | 支持 |
| Flexbox/网格 | 不支持 | 支持 |
| JavaScript语言 | 不可靠 | 完整的 ES6+ |
| PDF 操作 | 不可用 | 支持 |
| 数字签名 | 不可用 | 支持 |
| PDF/A合规性 | 不可用 | 支持 |
| 表格填写 | 不可用 | 支持 |
| 水印。 | 不可用 | 支持 |
| 合并/拆分 | 不可用 | 支持 |
| 页眉/页脚 | 仅限基本文本 | 完全支持 HTML |
| 安全补丁 | 永不(放弃) | 定期更新 |
API 架构差异
在研究初始化模式和基本用法时,可以立即发现TuesPechkin和IronPDF在架构上的差异。
TuesPechkin初始化复杂性
TuesPechkin 需要一个复杂的初始化过程,涉及转换器、工具集和部署配置:
// NuGet: Install-Package TuesPechkin
using TuesPechkin;
using System.IO;
class Program
{
static void Main()
{
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
string html = "<html><body><h1>Hello World</h1></body></html>";
byte[] pdfBytes = converter.Convert(new HtmlToPdfDocument
{
Objects = { new ObjectSettings { HtmlText = html } }
});
File.WriteAllBytes("output.pdf", pdfBytes);
}
}// NuGet: Install-Package TuesPechkin
using TuesPechkin;
using System.IO;
class Program
{
static void Main()
{
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
string html = "<html><body><h1>Hello World</h1></body></html>";
byte[] pdfBytes = converter.Convert(new HtmlToPdfDocument
{
Objects = { new ObjectSettings { HtmlText = html } }
});
File.WriteAllBytes("output.pdf", pdfBytes);
}
}Imports TuesPechkin
Imports System.IO
Class Program
Shared Sub Main()
Dim converter = New StandardConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New TempFolderDeployment())))
Dim html As String = "<html><body><h1>Hello World</h1></body></html>"
Dim pdfBytes As Byte() = converter.Convert(New HtmlToPdfDocument With {
.Objects = {New ObjectSettings With {.HtmlText = html}}
})
File.WriteAllBytes("output.pdf", pdfBytes)
End Sub
End Class这种模式需要理解多个嵌套类:TempFolderDeployment。 部署配置也必须与目标平台架构(x86/x64)相匹配。
IronPDF简化方法
IronPDF 通过简单明了的 API 完全消除了部署的复杂性:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html As String = "<html><body><h1>Hello World</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End ClassChromePdfRenderer 类可立即访问 PDF 生成,无需特定平台配置。 有关全面的 HTML 转换指导,请参阅 HTML 转 PDF 教程。
将 URL 转换为 PDF.
将网页转换为 PDF 文档展示了两个库之间的 API 可用性差异。
TuesPechkin实现
TuesPechkin在PageUrl属性来指定URL:
// NuGet: Install-Package TuesPechkin
using TuesPechkin;
using System.IO;
class Program
{
static void Main()
{
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
byte[] pdfBytes = converter.Convert(new HtmlToPdfDocument
{
Objects = {
new ObjectSettings {
PageUrl = "https://www.example.com"
}
}
});
File.WriteAllBytes("webpage.pdf", pdfBytes);
}
}// NuGet: Install-Package TuesPechkin
using TuesPechkin;
using System.IO;
class Program
{
static void Main()
{
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
byte[] pdfBytes = converter.Convert(new HtmlToPdfDocument
{
Objects = {
new ObjectSettings {
PageUrl = "https://www.example.com"
}
}
});
File.WriteAllBytes("webpage.pdf", pdfBytes);
}
}Imports TuesPechkin
Imports System.IO
Class Program
Shared Sub Main()
Dim converter = New StandardConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New TempFolderDeployment())))
Dim pdfBytes As Byte() = converter.Convert(New HtmlToPdfDocument With {
.Objects = {
New ObjectSettings With {
.PageUrl = "https://www.example.com"
}
}
})
File.WriteAllBytes("webpage.pdf", pdfBytes)
End Sub
End Class由于缺少 CSS3 和 JavaScript 支持,过时的 WebKit 引擎可能会错误地呈现现代网站。
IronPDF的实现
IronPDF 利用其现代 Chromium 引擎为 URL 渲染提供了专用方法:
// 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 ClassRenderUrlAsPdf 方法可在无头 Chromium 浏览器中加载页面,执行 JavaScript 并准确应用所有现代 CSS 样式。 这对于使用 React、Angular 或 Vue.js 等框架构建的网络应用程序至关重要,因为TuesPechkin无法正确呈现这些网络应用程序。
自定义渲染设置
配置页面尺寸、页边距和方向揭示了文档设置的不同方法。
TuesPechkin配置
TuesPechkin使用ObjectSettings类配置嵌套:
// NuGet: Install-Package TuesPechkin
using TuesPechkin;
using System.IO;
class Program
{
static void Main()
{
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
string html = "<html><body><h1>Custom PDF</h1></body></html>";
var document = new HtmlToPdfDocument
{
GlobalSettings = {
Orientation = GlobalSettings.PdfOrientation.Landscape,
PaperSize = GlobalSettings.PdfPaperSize.A4,
Margins = new MarginSettings { Unit = Unit.Millimeters, Top = 10, Bottom = 10 }
},
Objects = {
new ObjectSettings { HtmlText = html }
}
};
byte[] pdfBytes = converter.Convert(document);
File.WriteAllBytes("custom.pdf", pdfBytes);
}
}// NuGet: Install-Package TuesPechkin
using TuesPechkin;
using System.IO;
class Program
{
static void Main()
{
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
string html = "<html><body><h1>Custom PDF</h1></body></html>";
var document = new HtmlToPdfDocument
{
GlobalSettings = {
Orientation = GlobalSettings.PdfOrientation.Landscape,
PaperSize = GlobalSettings.PdfPaperSize.A4,
Margins = new MarginSettings { Unit = Unit.Millimeters, Top = 10, Bottom = 10 }
},
Objects = {
new ObjectSettings { HtmlText = html }
}
};
byte[] pdfBytes = converter.Convert(document);
File.WriteAllBytes("custom.pdf", pdfBytes);
}
}Imports TuesPechkin
Imports System.IO
Module Program
Sub Main()
Dim converter = New StandardConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New TempFolderDeployment())))
Dim html As String = "<html><body><h1>Custom PDF</h1></body></html>"
Dim document = New HtmlToPdfDocument With {
.GlobalSettings = New GlobalSettings With {
.Orientation = GlobalSettings.PdfOrientation.Landscape,
.PaperSize = GlobalSettings.PdfPaperSize.A4,
.Margins = New MarginSettings With {.Unit = Unit.Millimeters, .Top = 10, .Bottom = 10}
},
.Objects = {
New ObjectSettings With {.HtmlText = html}
}
}
Dim pdfBytes As Byte() = converter.Convert(document)
File.WriteAllBytes("custom.pdf", pdfBytes)
End Sub
End ModuleIronPDF配置
IronPDF在RenderingOptions属性中集中设置,具有直观的属性名称:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
string html = "<html><body><h1>Custom PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
string html = "<html><body><h1>Custom PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}Imports IronPdf
Imports IronPdf.Engines.Chrome
Imports System
Module Program
Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 10
renderer.RenderingOptions.MarginBottom = 10
Dim html As String = "<html><body><h1>Custom PDF</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("custom.pdf")
End Sub
End ModuleRenderingOptions 类提供了一种统一的配置方法,在该方法中,边距值直接以毫米为单位指定,而无需包装对象。
线程安全和并发性
线程安全是服务器端 PDF 生成的一个重要考虑因素,而这两个库采用了根本不同的方法。
TuesPechkin线程管理
TuesPechkin通过其ThreadSafeConverter宣传线程安全操作,但实现上有文档记录的限制:
//TuesPechkin- Even with ThreadSafeConverter, crashes under load
var converter = new TuesPechkin.ThreadSafeConverter(
new TuesPechkin.RemotingToolset<PechkinBindings>());
// Under high load, applications may experience:
// - System.AccessViolationException
// - StackOverflowException
// - Process hangs indefinitely
// - Memory corruption//TuesPechkin- Even with ThreadSafeConverter, crashes under load
var converter = new TuesPechkin.ThreadSafeConverter(
new TuesPechkin.RemotingToolset<PechkinBindings>());
// Under high load, applications may experience:
// - System.AccessViolationException
// - StackOverflowException
// - Process hangs indefinitely
// - Memory corruption' TuesPechkin- Even with ThreadSafeConverter, crashes under load
Dim converter = New TuesPechkin.ThreadSafeConverter(
New TuesPechkin.RemotingToolset(Of PechkinBindings)())
' Under high load, applications may experience:
' - System.AccessViolationException
' - StackOverflowException
' - Process hangs indefinitely
' - Memory corruption底层的 wkhtmltopdf 库并不是为高并发场景而设计的,即使采用了封装级线程管理,在高负载情况下仍会出现稳定性问题。
IronPDF本地并发性
IronPDF 提供本地线程安全,无需任何配置:
//IronPDF- Native thread safety
var renderer = new ChromePdfRenderer();
// Safe for concurrent use across multiple threads
// No AccessViolationException
// No process hangs
// Stable under high load//IronPDF- Native thread safety
var renderer = new ChromePdfRenderer();
// Safe for concurrent use across multiple threads
// No AccessViolationException
// No process hangs
// Stable under high load'IronPDF- Native thread safety
Dim renderer As New ChromePdfRenderer()
' Safe for concurrent use across multiple threads
' No AccessViolationException
' No process hangs
' Stable under high loadChromePdfRenderer在内部处理并发性,允许开发人员专注于应用程序逻辑而非线程同步。
支持现代 CSS 和 JavaScript.
在使用现代网络技术时,TruesPechkin 和IronPDF之间的渲染引擎差异最为明显。
TuesPechkin渲染限制
TuesPechkin 的 Qt WebKit 4.8 引擎早于现代 CSS 布局系统:
<div style="display: flex; justify-content: space-between; gap: 20px;">
<div style="flex: 1;">Column 1</div>
<div style="flex: 1;">Column 2</div>
</div>
<div style="display: grid; grid-template-columns: repeat(3, 1fr);">
<div>Grid Item 1</div>
<div>Grid Item 2</div>
<div>Grid Item 3</div>
</div>
<div style="display: flex; justify-content: space-between; gap: 20px;">
<div style="flex: 1;">Column 1</div>
<div style="flex: 1;">Column 2</div>
</div>
<div style="display: grid; grid-template-columns: repeat(3, 1fr);">
<div>Grid Item 1</div>
<div>Grid Item 2</div>
<div>Grid Item 3</div>
</div>使用TuesPechkin的应用程序必须依靠基于表格的布局或其他 CSS2.1 变通方法来实现多栏设计。
IronPDF现代渲染
IronPDF 的 Chromium 引擎支持所有现代 CSS 和 JavaScript:
// Modern CSS works correctly with IronPDF
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Renders correctly with full Flexbox support// Modern CSS works correctly with IronPDF
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Renders correctly with full Flexbox supportDim html As String = "
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>"
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
' Renders correctly with full Flexbox support这样,开发人员就可以使用相同的 HTML/CSS 进行网页显示和 PDF 生成,而无需维护单独的模板。
当团队考虑替代TuesPechkin时
有几种情况通常会促使开发团队评估TuesPechkin的替代方案:
安全要求
随着 CVE-2022-35583 被评为危急(9.8/10),以及底层 wkhtmltopdf 库被正式放弃,有安全合规性要求的组织不能继续使用 TuesPechkin。 SSRF 漏洞允许攻击者通过恶意 HTML 内容访问内部网络、窃取凭证和外泄数据。
现代网络技术的采用
采用现代前端框架(React、Angular、Vue.js)或 CSS 布局系统(Flexbox、Grid)的团队发现TuesPechkin无法准确呈现他们的内容。 过时的 WebKit 4.8 引擎不支持近十年来一直作为标准的技术。
负载下的稳定性
服务器端应用程序在并发PDF生成负载下遇到崩溃、挂起或AccessViolationException错误时,通常将这些问题追溯到TuesPechkin的线程限制。 即使有ThreadSafeConverter配置,底层的wkhtmltopdf库也不是为高并发环境设计的。
PDF 功能要求
TuesPechkin 只提供 HTML 到 PDF 的转换。 需要进行 PDF 操作(合并、拆分)、数字签名、PDF/A 合规性、表格填充或水印的团队必须添加额外的库,或考虑IronPDF等原生提供这些功能的替代工具。
简化部署
TuesPechkin的初始化模式与TempFolderDeployment增加了部署复杂性。 必须为每个目标环境正确配置特定平台的本地二进制文件。IronPDF通过标准的 NuGet 安装消除了这种复杂性。
API 映射参考
正在评估从TuesPechkin向IronPDF过渡的团队会发现此映射有助于理解概念等同:
| TuesPechkin | IronPDF |
|---|---|
StandardConverter / ThreadSafeConverter | ChromePdfRenderer |
HtmlToPdfDocument | 方法参数 |
GlobalSettings.PaperSize | RenderingOptions.PaperSize |
GlobalSettings.Orientation | RenderingOptions.PaperOrientation |
GlobalSettings.Margins | RenderingOptions.MarginTop/Bottom/Left/Right |
ObjectSettings.HtmlText | RenderHtmlAsPdf(html) |
ObjectSettings.PageUrl | RenderUrlAsPdf(url) |
RemotingToolset + Deployment | 不需要 |
[page] placeholder | {page} placeholder |
[toPage] placeholder | {total-pages} placeholder |
其他 PDF 功能
除了 HTML 到 PDF 的转换之外,IronPDF 还提供了TuesPechkin无法提供的文档操作功能:
-合并 PDF :将多个文档合并成单个文件 -拆分文档:将页面范围提取到单独的 PDF 文件中 -数字签名:应用加密签名来验证文档的真实性 -水印:通过 HTML/CSS 添加文本或图像水印
.NET兼容性和未来准备情况
TuesPechkin 的非活跃开发状态意味着不会对较新的 .NET 版本进行更新。IronPDFfor .NET 保持着定期更新的积极开发态势,确保与 .NET 8、.NET 9 和未来版本(包括预计于 2026 年发布的 .NET 10)的兼容性。该库的整个 API 均支持 async/await,符合现代 C# 开发实践,包括 C# 13 中的可用功能和预期的 C# 14 功能。
结论
TuesPechkin 和IronPDF代表了 .NET PDF 生成的不同时代。TuesPechkin提供了一个免费的、获得 MIT 许可的 wkhtmltopdf 封装器,但继承了严重的安全漏洞、过时的渲染引擎、复杂的线程管理要求以及负载下的稳定性问题。 底层技术已于 2022 年被弃用,没有安全补丁。
IronPDF 提供了一个现代化的、积极维护的替代方案,其基于 Chromium 的渲染引擎支持当前的网络技术。 它的本地线程安全性、全面的 PDF 功能和直接的 API 设计解决了 wkhtmltopdf 封装器固有的局限性。
对于目前使用TuesPechkin的团队来说,迁移的决定往往源于安全要求、渲染质量需要、稳定性问题或对基本 HTML 转换之外的 PDF 功能的要求。 这两个库之间的 API 映射简单明了,IronPDF 由于简化了初始化和配置模式,通常需要较少的代码。
有关更多实施指导,请浏览 IronPDF 文档和涵盖特定用例和高级功能的 教程。
