如何在PDF中替换文本 | IronPDF
TuesPechkin一直是周围wkhtmltopdf本地二进制的线程安全封装,帮助 .NET 开发人员多年来将HTML转换为PDF。 然而,底层wkhtmltopdf项目于2023年1月在GitHub上被存档,其依赖的WebKit分支大约于2015年。这带来了安全、稳定性和渲染限制,开发团队不可无视。
本指南提供了从TuesPechkin到IronPDF的完整迁移路径,为评估这一过渡的专业 .NET 开发人员提供了分步说明、代码比较和实用示例。
为什么现在就从TuesPechkin迁移
对于具有安全意识的开发团队来说,从TuesPechkin迁移的决定不再是可有可无的。 wkhtmltopdf 库的底层存在严重的未修补漏洞,这些漏洞将永远无法修复。
关键安全漏洞:CVE-2022-35583
| 属性 | 价值 |
|---|---|
| CVE ID | CVE-2022-35583 |
| 严重性 | CRITICAL (9.8/10) |
| 攻击向量 | 网络 |
| 状态 | 永不打补丁 |
| 受影响 | 所有TuesPechkin版本 |
wkhtmltopdf 维护者明确表示他们不会修复安全漏洞。 每个使用TuesPechkin的应用程序都会长期受到服务器端请求伪造 (SSRF) 攻击。
攻击如何工作
在处理用户提供的 HTML 时,攻击者可以注入恶意内容:
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-admin-panel:8080/api/users?export=all" />
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-admin-panel:8080/api/users?export=all" />
这使得攻击者可以访问 AWS/Azure/GCP 元数据端点、窃取内部 API 数据、对内部网络进行端口扫描并外泄敏感配置。
技术危机
TuesPechkin 包装了 wkhtmltopdf,它使用 Qt WebKit 4.8--前 Chrome 时代的古老技术。 这意味着:
- 不支持 Flexbox
- 不支持 CSS 网格
- JavaScript 执行中断
- 不支持 ES6+
稳定危机
即使在广告的ThreadSafeConverter下,TuesPechkin在高负载下仍然崩溃:
// ❌TuesPechkin- "ThreadSafeConverter" still crashes
var converter = new TuesPechkin.ThreadSafeConverter(
new TuesPechkin.RemotingToolset<PechkinBindings>());
// Under high load, you'll see:
// System.AccessViolationException: Attempted to read or write protected memory
// Process terminated unexpectedly
// Converter hangs indefinitely
// ❌TuesPechkin- "ThreadSafeConverter" still crashes
var converter = new TuesPechkin.ThreadSafeConverter(
new TuesPechkin.RemotingToolset<PechkinBindings>());
// Under high load, you'll see:
// System.AccessViolationException: Attempted to read or write protected memory
// Process terminated unexpectedly
// Converter hangs indefinitely
' ❌TuesPechkin- "ThreadSafeConverter" still crashes
Dim converter = New TuesPechkin.ThreadSafeConverter(
New TuesPechkin.RemotingToolset(Of PechkinBindings)())
' Under high load, you'll see:
' System.AccessViolationException: Attempted to read or write protected memory
' Process terminated unexpectedly
' Converter hangs indefinitely
IronPDF与 TuesPechkin:功能对比
了解架构差异有助于技术决策者评估迁移投资:
| 特征 | TuesPechkin | IronPDF |
|---|---|---|
| 许可 | 免费,开源 | 商业翻译 |
| 线程安全 | 需要人工管理 | 本地支持 |
| 货币 | 有局限性,在负载情况下可能会崩溃 | 稳健,可处理高并发 |
| 开发 | 不活跃,最后更新时间为 2015 年 | 积极、持续的改进 |
| 易用性 | 复杂的设置 | 方便用户使用的指南 |
| 文档 | 基本的 | 包含大量示例 |
| 安全性 | ❌ 关键 CVE | ✅ 无已知漏洞 |
| HTML 到 PDF | ⚠ 过时的WebKit | ✅ 现代 Chromium |
| CSS3代码 | ❌ 部分 | ✅ 已支持 |
| Flexbox/网格 | ❌ 不支持 | ✅ 已支持 |
| JavaScript语言 | ⚠ 不可靠 | ✅ 完全 ES6+ |
| PDF 操作 | ❌ 不可用 | ✅ 全文 |
| 数字签名 | ❌ 不可用 | ✅ 全文 |
| PDF/A合规性 | ❌ 不可用 | ✅ 全文 |
| 表格填写 | ❌ 不可用 | ✅ 全文 |
| 水印。 | ❌ 不可用 | ✅ 全文 |
| 合并/拆分 | ❌ 不可用 | ✅ 全文 |
快速入门:从 TuesPechkin 迁移到 IronPDF
迁移工作可以通过以下基本步骤立即开始。
步骤 1:替换 NuGet 软件包
删除所有TuesPechkin软件包:
# Remove TuesPechkin and all related packages
dotnet remove package TuesPechkin
dotnet remove package TuesPechkin.Wkhtmltox.Win64
dotnet remove package TuesPechkin.Wkhtmltox.Win32
# Remove TuesPechkin and all related packages
dotnet remove package TuesPechkin
dotnet remove package TuesPechkin.Wkhtmltox.Win64
dotnet remove package TuesPechkin.Wkhtmltox.Win32
安装 IronPDF:
# Install IronPDF
dotnet add package IronPdf
# Install IronPDF
dotnet add package IronPdf
步骤 2:删除本地二进制文件
从您的项目中删除这些文件和文件夹:
wkhtmltox.dllwkhtmltopdf.exe- 任何
wkhtmlto*文件 TuesPechkin.Wkhtmltox文件夹
步骤 3:更新命名空间
将TuesPechkin命名空间替换为IronPDF命名空间:
// Before (TuesPechkin)
using TuesPechkin;
using TuesPechkin.Wkhtmltox.Win64;
// After (IronPDF)
using IronPdf;
// Before (TuesPechkin)
using TuesPechkin;
using TuesPechkin.Wkhtmltox.Win64;
// After (IronPDF)
using IronPdf;
' Before (TuesPechkin)
Imports TuesPechkin
Imports TuesPechkin.Wkhtmltox.Win64
' After (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 库之间的复杂性差异。
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
IronPDF 方法:
// 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 Class
TuesPechkin版本需要创建一个带有复杂初始化链的TempFolderDeployment。 您还必须手动将字节写入文件。
IronPDF 完全消除了这一仪式。 创建一个ChromePdfRenderer,渲染HTML,然后保存。 代码是自文档化的,不需要了解部署工具集或特定平台的二进制管理。
有关 HTML 转 PDF 的高级应用场景,请参阅 HTML 转 PDF 指南。
将 URL 转换为 PDF
URL 到 PDF 的转换也存在类似的复杂性差异。
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())));
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
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
TuesPechkin在ObjectSettings.PageUrl。 IronPDF提供了一个专用的RenderUrlAsPdf方法,可以清晰表达意图。
请浏览 URL to PDF 文档,了解身份验证和自定义页眉选项。
自定义渲染设置
页面方向、纸张大小和页边距要求采用不同的配置方法。
TuesPechkin 方法:
// NuGet: Install-Package TuesPechkin
// NuGet: Install-Package TuesPechkin.Wkhtmltox.Win64
using TuesPechkin;
using System.Drawing.Printing;
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.PaperOrientation.Landscape,
PaperSize = PaperKind.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
// NuGet: Install-Package TuesPechkin.Wkhtmltox.Win64
using TuesPechkin;
using System.Drawing.Printing;
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.PaperOrientation.Landscape,
PaperSize = PaperKind.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.Drawing.Printing
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.PaperOrientation.Landscape,
.PaperSize = PaperKind.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 Module
IronPDF 方法:
// 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 Module
TuesPechkin将设置分为用于文档范围选项的ObjectSettings。 IronPDF将所有内容合并到RenderingOptions中,具有清晰可发现的属性名称。
TuesPechkinAPI 到IronPDF映射参考
这种映射通过显示直接的 API 对应关系来加速迁移:
| TuesPechkin | IronPDF |
|---|---|
StandardConverter |
ChromePdfRenderer |
ThreadSafeConverter |
ChromePdfRenderer |
HtmlToPdfDocument |
方法参数 |
GlobalSettings |
RenderingOptions |
ObjectSettings.HtmlText |
RenderHtmlAsPdf(html) |
ObjectSettings.PageUrl |
RenderUrlAsPdf(url) |
GlobalSettings.PaperSize |
RenderingOptions.PaperSize |
GlobalSettings.Orientation |
RenderingOptions.PaperOrientation |
MarginSettings |
MarginBottom,等等。 |
[page]占位符 |
{page}占位符 |
[topage]占位符 |
{total-pages}占位符 |
RemotingToolset |
不需要 |
Win64EmbeddedDeployment |
不需要 |
TempFolderDeployment |
不需要 |
常见迁移问题和解决方案
问题 1:复杂的初始化代码
问题:TuesPechkin需要复杂的转换器设置和部署工具集。
解决方案:IronPDF 很简单:
// Before (TuesPechkin)
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
// After (IronPDF)
var renderer = new ChromePdfRenderer();
// That's it!
// Before (TuesPechkin)
var converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
// After (IronPDF)
var renderer = new ChromePdfRenderer();
// That's it!
' Before (TuesPechkin)
Dim converter = New StandardConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New TempFolderDeployment())))
' After (IronPDF)
Dim renderer = New ChromePdfRenderer()
' That's it!
问题 2:线程安全崩溃
问题: TuesPechkin的AccessViolationException的情况下崩溃。
解决方案:IronPDF具有本地线程安全功能,无需特殊配置:
//IronPDFis inherently thread-safe
var renderer = new ChromePdfRenderer();
// Use from any thread without crashes
//IronPDFis inherently thread-safe
var renderer = new ChromePdfRenderer();
// Use from any thread without crashes
'IronPDF is inherently thread-safe
Dim renderer As New ChromePdfRenderer()
' Use from any thread without crashes
问题 3:页码占位符语法
问题: TuesPechkin使用[topage]占位符。
解决方案:更新IronPDF的占位符语法:
// Before (TuesPechkin)
"Page [page] of [topage]"
// After (IronPDF)
"Page {page} of {total-pages}"
// Before (TuesPechkin)
"Page [page] of [topage]"
// After (IronPDF)
"Page {page} of {total-pages}"
' Before (TuesPechkin)
"Page [page] of [topage]"
' After (IronPDF)
"Page {page} of {total-pages}"
问题 4:CSS 布局已损坏
问题:由于 wkhtmltopdf 使用 Qt WebKit 4.8,因此 Flexbox 和网格布局无法在TuesPechkin中使用。
解决方案:使用IronPDF适当的现代 CSS:
// Remove table-based workarounds, use modern CSS
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html);
// Works correctly with Chromium!
// Remove table-based workarounds, use modern CSS
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html);
// Works correctly with Chromium!
' Remove table-based workarounds, use modern CSS
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 correctly with Chromium!
问题 5:本地二进制管理
问题:TuesPechkin需要特定平台的 wkhtmltopdf 二进制文件和路径配置。
解决方案:IronPDF 通过 NuGet 处理所有依赖关系,无需管理本地二进制文件:
# Just install the package
dotnet add package IronPdf
# No wkhtmltopdf binaries needed
# Just install the package
dotnet add package IronPdf
# No wkhtmltopdf binaries needed
TuesPechkin迁移清单
迁移前任务
审核您的代码库,确定所有TuesPechkin的使用情况:
grep -r "using TuesPechkin" --include="*.cs" .
grep -r "ThreadSafeConverter\|RemotingToolset" --include="*.cs" .
grep -r "using TuesPechkin" --include="*.cs" .
grep -r "ThreadSafeConverter\|RemotingToolset" --include="*.cs" .
记录当前GlobalSettings配置(纸张大小、方向、边距)。 记录ObjectSettings配置(HTML内容、URLs)。 确定转换的页眉/页脚实现。 查找所有 wkhtmltopdf 二进制文件以进行删除。
代码更新任务
1.删除TuesPechkinNuGet 软件包 2.删除本地 wkhtmltopdf 二进制文件
- 安装IronPDF NuGet包
- 更新using语句从
IronPdf5.在启动时添加许可证密钥初始化 - 用
ChromePdfRenderer替换转换器 - 将
RenderingOptions - 将
ObjectSettings转换为方法参数 9.将边距配置更新为单个属性 - 更新页眉/页脚语法到基于HTML的
HtmlHeaderFooter - 修复页面占位符语法(
[page]→{page}) 12.删除所有部署/工具集代码
迁移后测试
迁移后,验证这些方面:
- 运行所有单元测试
- 测试线程安全场景(IronPDF 可处理多线程而不会崩溃)
- 比较 PDF 输出质量(Chromium 的渲染更准确)
- 验证 CSS 呈现(Flexbox 和 Grid 现在可以使用)
- 测试 JavaScript 的执行(现在支持 ES6+)
- 测试页眉/页脚渲染
- 性能测试批量操作
- 安全扫描以验证没有 wkhtmltopdf 二进制文件残留
迁移到IronPDF的主要优势
从TuesPechkin迁移到IronPDF有几个关键优势:
安全性:CVE-2022-35583和其他 wkhtmltopdf 漏洞已消除。IronPDF的 Chromium 引擎会定期接受安全更新。
原生线程安全:不再需要复杂的ThreadSafeConverter配置。 在负载下不再有AccessViolationException崩溃。IronPDF自动处理并发性。
现代渲染引擎:完全支持 CSS3、Flexbox、Grid 和 ES6+ JavaScript。 您的 PDF 将与现代浏览器中显示的内容完全一致。
简化部署:无需管理特定于平台的二进制文件。 没有TempFolderDeployment礼节。 安装 NuGet 软件包即可。
活跃开发:IronPDF的定期更新保证了与当前和即将到来的 .NET 版本的兼容性。
扩展功能:TuesPechkin仅将 HTML 转换为 PDF。IronPDF增加了 PDF 操作、数字签名、PDF/A 合规性、表格填充、水印和合并/拆分操作。

