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"/>當wkhtmltopdf渲染此 HTML 時,它會從伺服器的網路上下文擷取這些 URL,繞過防火牆和安全控制。 此漏洞永遠不會被修補,因為該專案已被正式放棄。
了解 IronPDF
IronPDF 提供了一個強大的替代方案,可解決wkhtmltopdf的缺點。 IronPDF透過積極的維護、定期的更新,以及依賴目前的 Chromium 渲染引擎,提供安全性與符合現代網路標準的功能。
主要特點包括
- 現代 Chromium 引擎:使用目前的 Chromium 渲染引擎,支援完整的 ES2024 JavaScript
- 無已知 CVE:零已知安全漏洞
- 主動開發:定期發佈安全更新和功能增強
- 完整的 CSS 支援:完整的 CSS 網格、Flexbox 與現代佈局系統
- 全面的 PDF 功能:數位簽章、符合 PDF/A 規範、PDF 操作功能
- 專業支援:詳盡的文件和專業的支援管道
功能比較
下表強調了wkhtmltopdf與IronPDF的基本差異:
| 特點 | wkhtmltopdf | IronPDF |
|---|---|---|
| 授權 | 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此模式需要使用 PdfTools 建立同步轉換器、使用 GlobalSettings 和 Objects 集合建構<編碼>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.comChromePdfRenderer類取消了巢狀配置物件,返回一個內建儲存方法的 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.comIronPDF實作。
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.comRenderUrlAsPdf 方法利用 Chromium 引擎來呈現具有完整JavaScript執行和現代 CSS 支援的頁面 - 這些功能受限於wkhtmltopdf的 2015 WebKit 引擎。
自訂 PDF 設定
配置頁面尺寸、邊緣和方向可揭示 API 之間的結構差異。
wkhtmltopdf自訂設定
wkhtmltopdf 需要嵌套 GlobalSettings 與 MarginSettings 物件:
// 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.comIronPDF自訂設定
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.comAPI 對應參考。
評估從wkhtmltopdf過渡到IronPDF的團隊會發現此對應圖有助於瞭解概念等同性:
CLI 至 C# API 對應。
| wkhtmltopdf CLI 選項 | IronPdf 同等級產品 | 筆記 |
|---|---|---|
wkhtmltopdf 輸入.html 輸出.pdf。 | renderer.RenderHtmlFileAsPdf()。 | 檔案至 PDF |
wkhtmltopdf URL output.pdf | renderer.RenderUrlAsPdf()。 | URL 至 PDF |
--頁面大小 A4。 | RenderingOptions.PaperSize=PdfPaperSize.A4渲染選項。 | 紙張大小 |
--頁面大小 Letter | RenderingOptions.PaperSize=PdfPaperSize.Letter渲染選項。 | 美國信件 |
--面向景觀 | RenderingOptions.PaperOrientation = Landscape。 | 導向 |
--margin-top 10mm | RenderingOptions.MarginTop = 10 | 邊距(以毫米為單位 |
--margin-bottom 10mm | RenderingOptions.MarginBottom = 10。 | |
--margin-left 10mm | RenderingOptions.MarginLeft = 10。 | |
--margin-right 10mm | RenderingOptions.MarginRight = 10。 | |
--header-html header.html | <編碼>RenderingOptions.HtmlHeader</編碼 | HTML 標題 |
--footer-html footer.html | RenderingOptions.HtmlFooter | HTML 頁腳 |
--footer-center "[page]" | {page} 占位符 | 頁數 |
--footer-center "[toPage]" | {total-pages} 占位符 | 總頁數 |
| <編碼>--enable-javascript</編碼 | 預設啟用 | JavaScript |
--javascript-delay 500 | RenderingOptions.WaitFor.RenderDelay = 500。 | JS 延遲 |
---print-media-type (列印媒體類型) | RenderingOptions.CssMediaType = Print。 | CSS 媒體 |
--dpi 300 | RenderingOptions.Dpi=300 | DPI 設定 |
| <編碼>--grayscale</編碼 | RenderingOptions.GrayScale=true | 灰階 |
--zoom 0.8。 | RenderingOptions.Zoom=80 | 縮放 (%) |
C# Wrapper API 對應。
| wkhtmltopdf Wrapper | IronPDF | 筆記 |
|---|---|---|
同步轉換器 | <代碼>ChromePdfRenderer</代碼 | 主要呈現器 |
| <編碼>HtmlToPdfDocument</編碼 | 渲染選項 | 配置 |
GlobalSettings.Out | <代碼>pdf.SaveAs()</代碼 | 輸出檔案 |
GlobalSettings.PaperSize | RenderingOptions.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無法提供的文件操作功能:
- 合併 PDFs:將多個文件合併為單一檔案
- 分割文件:將頁面範圍萃取到獨立的 PDF 中
- 數位簽章:應用加密簽章來確保文件的真實性
- 水印:新增文字或影像水印
- IronPDF/A Compliance:產生符合歸檔標準的文件
- Form Filling:以程式化方式填入 PDF 表單欄位
- 密碼保護:使用使用者和所有者密碼為 PDF 加密
- 頁首和頁尾:完全支援 HTML/CSS 的自動頁碼和品牌化功能
同步支援
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此功能可防止高負載 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 文件和涵蓋特定用例和進階功能的 教學。