IRONSOFTWAREHOME
视频

如何在 C# | IronPDF 中添加目录

Curtis Chau
Curtis Chau
Updated: 2026年7月19日

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.62020年6月11日
底层引擎Qt 4.8 + QtWebKit(Qt 4.8 于2015年终止支持)已关闭
CSS 网格支持None破译
Flexbox 支持部分翻译破译
ES6+JavaScript>有限的破译

SSRF 攻击如何工作

服务器端请求伪造漏洞允许攻击者访问内部服务、窃取凭证、扫描您的内部网络并通过伪造的 HTML 外泄敏感数据:

<!-- Malicious HTML submitted to your PDF generator -->
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>
HTML

当 wkhtmltopdf 渲染 HTML 时,它会绕过防火墙和安全控制,从服务器的网络上下文中获取这些 URL。

受影响的封装库

每个.NET包装器都绑定或外壳使用相同的wkhtmltopdf本地二进制,所以它们无论包装器本身多活跃,都会继承其CVE漏洞:

封装库最新的NuGet安全风险
DinkToPdf1.0.8(2017年4月) - 被遗弃继承CVE-2022-35583
Rotativa.AspNetCore(webgio的分支)1.4.0(2023年11月) - 包装器更新,二进制冻结继承CVE-2022-35583
TuesPechkin2.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:功能对比

了解架构差异有助于技术决策者评估迁移投资:

特征wkhtmltopdfIronPDF
许可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.
SHELL

步骤2:安装IronPDF

# AddIronPDF(secure, modern alternative)
dotnet add package IronPdf
SHELL

步骤 3:更新命名空间

将wkhtmltopdf命名空间替换为IronPDF命名空间:

// Before (wkhtmltopdf)
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;

// After (IronPDF)
using IronPdf;

步骤 4:初始化许可证

在应用程序启动时添加许可证初始化:

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);
    }
}

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");
    }
}

wkhtmltopdf 需要创建一个 SynchronizedConverter 使用 PdfTools,构造一个 HtmlToPdfDocument 使用 GlobalSettingsObjects,设置属性比如 ColorMode, OrientationPaperSize,调用 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);
    }
}

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");
    }
}

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);
    }
}

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");
    }
}

wkhtmltopdf 在 GlobalSettingsObjects 中嵌套设置,MarginSettings 作为一个独立的对象。IronPDF提供直接的 RenderingOptions 属性,名称清晰如 PaperOrientation, MarginTopPaperSize

wkhtmltopdf API 到IronPDF映射参考

这种映射通过显示直接的 API 对应关系来加速迁移:

CLI 到IronPDF的映射

wkhtmltopdf CLI 选项IronPDF 同等产品
wkhtmltopdf input.html output.pdfrenderer.RenderHtmlFileAsPdf()
wkhtmltopdf URL output.pdfrenderer.RenderUrlAsPdf()
--page-size A4RenderingOptions.PaperSize = PdfPaperSize.A4
--page-size LetterRenderingOptions.PaperSize = PdfPaperSize.Letter
--orientation LandscapeRenderingOptions.PaperOrientation = Landscape
--margin-top 10mmRenderingOptions.MarginTop = 10
--margin-bottom 10mmRenderingOptions.MarginBottom = 10
--margin-left 10mmRenderingOptions.MarginLeft = 10
--margin-right 10mmRenderingOptions.MarginRight = 10
--header-html header.htmlRenderingOptions.HtmlHeader
--footer-center "[page]"{page} placeholder
--footer-center "[toPage]"{total-pages} placeholder
--enable-javascript默认已启用
--javascript-delay 500RenderingOptions.WaitFor.RenderDelay = 500
--dpi 300RenderingOptions.Dpi = 300
--grayscaleRenderingOptions.GrayScale = true

C#包装API映射

wkhtmltopdf 封装程序IronPDF
SynchronizedConverterChromePdfRenderer
HtmlToPdfDocumentRenderingOptions
GlobalSettings.Outpdf.SaveAs()
GlobalSettings.PaperSizeRenderingOptions.PaperSize
GlobalSettings.OrientationRenderingOptions.PaperOrientation
GlobalSettings.MarginsRenderingOptions.Margin*
ObjectSettings.PageRenderHtmlFileAsPdf()
ObjectSettings.HtmlContentRenderHtmlAsPdf()
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
};

问题 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");

问题 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);

第 4 期:同步与异步渲染

**wkhtmltopdf:**封装器是同步和阻塞线程。

**解决方案:**IronPDF支持异步渲染:

public async Task<byte[]> GeneratePdfAsync(string html)
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}

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" .
SHELL

查找并记录 wkhtmltopdf 二进制文件,以便删除。 文档当前设置(纸张大小、页边距、页眉/页脚)。

代码更新任务

1.删除所有 wkhtmltopdf 封装 NuGet 软件包 2.删除 wkhtmltopdf 二进制文件(wkhtmltopdf.exe、wkhtmltox.dll) 3. 安装IronPDF NuGet包 4. 更新命名空间导入,从 Haukcode.WkHtmlToPdfDotNet (或您使用的包装器) 到 IronPdf 5. 用 ChromePdfRenderer 替换 SynchronizedConverter 6. 将 HtmlToPdfDocument 模式转换为直接渲染方法 7. 更新 GlobalSettings 配置为 RenderingOptions 8. 将边距配置从 MarginSettings 转换为独立属性 9. 更新占位符语法 ([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
SHELL

迁移到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 应用程序中的线程阻塞。

请注意: DinkToPdf、NReco、Rotativa、TuesPechkin和wkhtmltopdf是其各自所有者的注册商标。 本网站与DinkToPdf、NReco、Rotativa、TuesPechkin或wkhtmltopdf没有关联、认可或赞助关系。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。
Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户