比較

wkhtmltopdf vs IronPDF:技術比較指南

wkhtmltopdfvs IronPDF:.NET PDF 生成的技術比較

當 .NET 開發人員需要將 HTML 轉換成 PDF 時,wkhtmltopdf 因其開放原始碼的特性和命令列的簡易性,歷來都是很受歡迎的選擇。 然而,專案的放棄和嚴重的安全漏洞促使許多團隊評估現代的替代方案。 本技術比較將wkhtmltopdf與IronPDF一併檢視,以協助架構人員和開發人員瞭解兩者在安全勢態、渲染能力和長期可行性方面的顯著差異。

瞭解 wkhtmltopdf

wkhtmltopdf 是一款將 HTML 轉換為 PDF 文件的工具,可直接從命令列操作,並利用 Qt WebKit 來處理 HTML 內容。 在多年的積極開發過程中,該函式庫因其免費的 LGPLv3 授權和跨平台可用性而廣受歡迎。

然而,wkhtmltopdf 現在提出了不容忽視的重要挑戰:

  • 專案放棄:最後一次有意義的軟體更新發生在 2016-2017 年左右
  • 關鍵安全漏洞:CVE-2022-35583 (CVSS 9.8 嚴重性) 是仍未修補的 SSRF 漏洞。
  • 過時的渲染引擎:依賴 2015 年的 Qt WebKit
  • 有限的現代網路支援:無 CSS Grid 支援、Flexbox 實作崩潰、無 ES6+ JavaScript
  • 生態系統停滯不前:所有 .NET wrapper 函式庫(DinkToPdf、Rotativa、TuesPechkin、WkHtmlToPdf-DotNet、NReco.PdfGenerator)都繼承了這些漏洞

CVE-2022-35583 安全危機

wkhtmltopdf 的伺服器端請求偽造 (SSRF) 漏洞可讓攻擊者

  • 存取內部服務:接達防火牆後的內部 API、資料庫和服務
  • Steal Credentials:存取雲端元資料端點 (AWS、GCP、Azure) 以竊取 IAM 認證
  • 連接埠掃描:從基礎架構內掃描內部網路
  • Data Exfiltration:透過精心製作的 HTML/CSS 擷取敏感資料

攻擊媒介很直接-惡意 HTML 提交給 PDF 產生器:

<!-- 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"/>
<!-- 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,繞過防火牆和安全控制。 此漏洞永遠不會被修補,因為該專案已被正式放棄。

了解 IronPDF

IronPDF 提供了一個強大的替代方案,可解決wkhtmltopdf的缺點。 IronPDF透過積極的維護、定期的更新,以及依賴目前的 Chromium 渲染引擎,提供安全性與符合現代網路標準的功能。

主要特點包括

  • 現代 Chromium 引擎:使用目前的 Chromium 渲染引擎,支援完整的 ES2024 JavaScript
  • 無已知 CVE:零已知安全漏洞
  • 主動開發:定期發佈安全更新和功能增強
  • 完整的 CSS 支援:完整的 CSS 網格、Flexbox 與現代佈局系統
  • 全面的 PDF 功能:數位簽章、符合 PDF/A 規範、PDF 操作功能
  • 專業支援:詳盡的文件和專業的支援管道

功能比較

下表強調了wkhtmltopdf與IronPDF的基本差異:

特點wkhtmltopdfIronPDF
授權LGPLv3 (免費)商業的
渲染引擎Qt WebKit (2015)目前的 Chromium 引擎
安全狀態CVE-2022-35583 危急 (9.8) 未修補程式碼無已知 CVE
最近一次有意義的更新2016-2017主動開發
CSS 網格不支援全面支援
<強>Flexbox</強破損全面支援
ES6+ JavaScript不支援全面支援
Async/等待不支援全面支援
PDF 操作不支援全面支援
數位簽名不支援全面支援
PDF/A合規性不支援全面支援
專業支援無(已放棄)有 SLA 的商業翻譯
C# 整合透過第三方包裝直接、定期更新

受影響的套用程式庫

wkhtmltopdf 的所有 .NET wrapper 都繼承了相同的漏洞:

包裝程式庫狀態安全風險
DinkToPdf重點
<強>Rotativa</強重點
TuesPechkin重點
WkHtmlToPdf-DotNet重點
NReco.PdfGenerator使用 wkhtmltopdf重點

如果您的應用程式使用任何這些函式庫,就有可能受到 CVE-2022-35583 的攻擊。

API 架構差異

wkhtmltopdf wrappers 和IronPDF之間的 API 模式顯示出在複雜性和可用性上的顯著差異。

wkhtmltopdf配置模式

wkhtmltopdf wrappers 需要使用嵌套的設定配置來建立文件物件:

// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using 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.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 WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using 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.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);
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

此模式需要使用 PdfTools 建立同步轉換器、使用 GlobalSettingsObjects 集合建構<編碼>HtmlToPdfDocument</編碼以及手動寫入 byte array 到檔案。

IronPDF簡化模式

IronPDF 使用<代碼>ChromePdfRenderer</代碼類簡化方法:

// 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");
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

ChromePdfRenderer類取消了巢狀配置物件,返回一個內建儲存方法的 PdfDocument 。 如需全面的 HTML 轉換指南,請參閱 HTML to PDF 教學

URL 至 PDF 轉換

將網頁轉換為 PDF 展示了兩種方法的複雜性差異。

wkhtmltopdf實作

wkhtmltopdf 使用 ObjectSettings 內的 Page 屬性來指定 URL:

// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using 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.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 WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using 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.Portrait,
                PaperSize = PaperKind.A4
            },
            Objects = {
                new ObjectSettings()
                {
                    Page = "https://www.example.com"
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("webpage.pdf", pdf);
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

IronPDF實作。

IronPDF 提供了專用的 RenderUrlAsPdf 方法:

// 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");
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

RenderUrlAsPdf 方法利用 Chromium 引擎來呈現具有完整JavaScript執行和現代 CSS 支援的頁面 - 這些功能受限於wkhtmltopdf的 2015 WebKit 引擎。

自訂 PDF 設定

配置頁面尺寸、邊緣和方向可揭示 API 之間的結構差異。

wkhtmltopdf自訂設定

wkhtmltopdf 需要嵌套 GlobalSettingsMarginSettings 物件:

// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using 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.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 WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using 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.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);
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

IronPDF自訂設定

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");
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

API 對應參考。

評估從wkhtmltopdf過渡到IronPDF的團隊會發現此對應圖有助於瞭解概念等同性:

CLI 至 C# API 對應。

wkhtmltopdf CLI 選項IronPdf 同等級產品筆記
wkhtmltopdf 輸入.html 輸出.pdfrenderer.RenderHtmlFileAsPdf()檔案至 PDF
wkhtmltopdf URL output.pdfrenderer.RenderUrlAsPdf()URL 至 PDF
--頁面大小 A4RenderingOptions.PaperSize=PdfPaperSize.A4渲染選項。紙張大小
--頁面大小 LetterRenderingOptions.PaperSize=PdfPaperSize.Letter渲染選項。美國信件
--面向景觀RenderingOptions.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.html<編碼>RenderingOptions.HtmlHeader</編碼HTML 標題
--footer-html footer.htmlRenderingOptions.HtmlFooterHTML 頁腳
--footer-center "[page]"{page} 占位符頁數
--footer-center "[toPage]"{total-pages} 占位符總頁數
<編碼>--enable-javascript</編碼預設啟用JavaScript
--javascript-delay 500RenderingOptions.WaitFor.RenderDelay = 500JS 延遲
---print-media-type (列印媒體類型)RenderingOptions.CssMediaType = PrintCSS 媒體
--dpi 300RenderingOptions.Dpi=300DPI 設定
<編碼>--grayscale</編碼RenderingOptions.GrayScale=true灰階
--zoom 0.8RenderingOptions.Zoom=80縮放 (%)

C# Wrapper API 對應。

wkhtmltopdf WrapperIronPDF筆記
同步轉換器<代碼>ChromePdfRenderer</代碼主要呈現器
<編碼>HtmlToPdfDocument</編碼渲染選項配置
GlobalSettings.Out<代碼>pdf.SaveAs()</代碼輸出檔案
GlobalSettings.PaperSizeRenderingOptions.PaperSize紙張大小
GlobalSettings.Orientation<編碼>RenderingOptions.PaperOrientation</編碼導向
GlobalSettings.邊界RenderingOptions.Margin*個別邊距
ObjectSettings.Page 物件設定頁面<代碼>RenderHtmlFileAsPdf()</代碼檔案輸入
ObjectSettings.HtmlContent 物件設定。<代碼>RenderHtmlAsPdf()</代碼HTML 字串
<編碼>HeaderSettings.Center</編碼<編碼>TextHeader.CenterText</編碼標題文字
<編碼>FooterSettings.Center</編碼<編碼>TextFooter.CenterText</編碼頁尾文字
converter.Convert(doc)<編碼>renderer.RenderHtmlAsPdf()</編碼生成 PDF

占位符語法對應

wkhtmltopdf 占位符IronPdf 占位符
[page]{page}
[toPage]{總頁數}
[日期]<編碼>{日期}</編碼
[時間]{time}
[標題]<編碼>{html-title}</編碼
<編碼>[url]</編碼<編碼>{url}</編碼

當團隊考慮從wkhtmltopdf轉移到IronPDF時。

有幾種情況通常會促使開發團隊評估 IronPDF,將其作為wkhtmltopdf的替代方案:

安全合規要求

有安全合規要求(SOC 2、PCI DSS、HIPAA)的機構不能接受有已知關鍵漏洞的應用程式。 CVE-2022-35583 的 9.8 嚴重性等級會在大多數安全框架中觸發立即修復的要求。

現代 CSS 架構的採用

採用 Bootstrap 5、Tailwind CSS 或自訂 CSS 網格佈局的團隊會發現wkhtmltopdf無法正確呈現這些佈局。 2015 WebKit 引擎完全不支援 CSS Grid,且已破解 Flexbox 實作。

JavaScript應用程式需求

使用現代JavaScript功能的應用程式 -ES6+ 語法,包括箭頭函數、async/await、類別和範本字面意義 - 會在wkhtmltopdf中遇到故障。IronPDF的 Chromium 引擎提供完整的JavaScript支援。

雲端與容器部署

使用 Docker、Kubernetes 或雲端平台的現代部署策略可從 IronPdf 的容器友善架構中獲益。 容器中wkhtmltopdf二進位檔的安全掃描會標示 CVE 漏洞。

長期維護的顧慮

由於wkhtmltopdf未來預計不會更新,因此隨著網路標準的演進,團隊面臨越來越多的技術債務。IronPDF的積極開發可確保與未來的 .NET 版本持續相容,包括預計在 2026 年推出的 .NET 10。

IronPDF的其他功能

除了 HTML 到 PDF 的轉換之外,IronPDF 還提供wkhtmltopdf無法提供的文件操作功能:

同步支援

IronPdf 為網路應用程式效能提供 async/await 支援:

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;
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

此功能可防止高負載 Web 應用程式中的線程阻塞 - 這是wkhtmltopdf僅同步封裝程式所不具備的功能。

.NET相容性與未來準備

wkhtmltopdf 的放棄意味著不會針對較新的 .NET 版本進行相容性測試或更新。IronPDFfor .NET 維持積極的開發與定期的更新,確保與 .NET 8、.NET 9 以及未來的版本相容,包括預計在 2026 年推出的 .NET 10。該函式庫整個 API 的 async/await 支援符合現代 C# 開發實務,包括 C# 14 中預期的功能。

結論

wkhtmltopdf 和IronPDF在安全性、渲染能力和長期可行性方面存在顯著差異。wkhtmltopdf的關鍵 SSRF 漏洞 (CVE-2022-35583) 與專案放棄結合,為生產應用程式創造出無法維持的安全勢態。 2015 WebKit 引擎無法處理現代的 CSS Grid、Flexbox 支援失效,並且在 ES6+JavaScript上失敗。

IronPdf 基於 Chromium 的渲染引擎提供對現代網路標準的完整支援,同時維持零已知 CVE。 其簡化的 API 設計 - 方法如<代碼>RenderHtmlAsPdf()</代碼和 SaveAs() 而非嵌套的組態物件 - 降低了程式碼的複雜性,同時增加了wkhtmltopdf無法提供的功能,如 PDF 操作、數位簽章和同步支援。

對於目前使用wkhtmltopdf或其封裝函式庫 (DinkToPdf、Rotativa、TuesPechkin) 的團隊而言,其安全性影響需要立即評估替代方案。wkhtmltopdfCLI 選項與IronPDF的 RenderingOptions 之間的 API 對應非常直接,而且IronPDF始終需要較少的程式碼,同時消除了wkhtmltopdf中固有的安全風險。

如需其他實施指導,請參閱 IronPDF 文件和涵蓋特定用例和進階功能的 教學