如何在 C# 中從 wkhtmltopdf 轉移到 IronPDF
wkhtmltopdf 一直是使用 Qt WebKit 將 HTML 文件轉換為 PDF 的廣泛工具。 儘管該專案因其命令列功能和免費授權而廣受開發人員歡迎,但現在卻出現了再也不能忽視的重大安全風險。 該函式庫已於 2016-2017 年正式棄用,一個 CRITICAL 嚴重性漏洞 (CVE-2022-35583) 仍永久未修補。
本指南提供了從wkhtmltopdf到IronPDF的完整轉換路徑,並提供逐步說明、程式碼比較以及實用範例,適合需要從應用程式中消除此安全風險的專業 .NET 開發人員使用。
重要安全警告:CVE-2022-35583
wkhtmltopdf 包含永遠無法修復的重要安全漏洞:
| 問題 | 嚴重性 | 狀態 |
|---|---|---|
| CVE-2022-35583 | 關鍵 (9.8/10) | UNPATCHED 未修訂。 |
| SSRF 漏洞 | 基礎架構接管風險 | UNPATCHED 未修訂。 |
| 最近更新 | 2016-2017 | 被拋棄。 |
| WebKit版本 | 2015 (Qt WebKit) | OBSOLETE 刪除。 |
| CSS 網格支援 | 無 | 破損 |
| Flexbox 支援 | 部分的 | 破損 |
| ES6+ JavaScript。 | 無 | 破損 |
SSRF 攻擊如何運作
伺服器端請求偽造漏洞允許攻擊者存取內部服務、竊取憑證、掃描您的內部網路,並透過精心製作的 HTML 外洩敏感資料:
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>
當wkhtmltopdf渲染此 HTML 時,它會從您伺服器的網路上下文擷取這些 URL,繞過防火牆和安全控制。
受影響的套用程式庫
wkhtmltopdf 的所有 .NET wrapper 都會繼承這些漏洞:
| 包裝程式庫 | 狀態 | 安全風險 |
|---|---|---|
| DinkToPdf | 棄 | ⚠️ CRITICAL |
| <強>Rotativa</強 | 棄 | ⚠️ CRITICAL |
| TuesPechkin | 棄 | ⚠️ CRITICAL |
| WkHtmlToPdf-DotNet | 棄 | ⚠️ CRITICAL |
| NReco.PdfGenerator | 使用 wkhtmltopdf | ⚠️ CRITICAL |
如果您使用任何這些函式庫,就有可能受到 CVE-2022-35583 的攻擊。
IronPDFvs wkhtmltopdf:功能比較
了解架構上的差異有助於技術決策者評估遷移投資:
| 特點 | wkhtmltopdf | IronPDF |
|---|---|---|
| 授權 | LGPLv3 (免費) | 商業的 |
| 渲染引擎 | Qt WebKit (2015) | 目前的 Chromium 引擎 |
| 安全漏洞 | CVE-2022-35583, 主要未修補問題 | 無已知 CVE |
| 主動維護 | 已放棄,自 2017 年起無任何有意義的更新 | 定期發佈,積極維護 |
| 支援現代網路標準 | 受限(flexbox 斷裂、無 CSS Grid) | 支援 |
| 整合與支援 | 僅限於社群論壇 | 廣泛的文件和專門的支援 |
| CSS 網格 | ❌ 不支援 | ✅ 已支援 |
| <強>Flexbox</強 | ⚠️ 破譯 | ✅ 已支援 |
| ES6+ JavaScript。 | ❌ 不支援 | ✅ 已支援 |
| Async/等待 | ❌ 不支援 | ✅ 已支援 |
| PDF 操作 | ❌ 不支援 | ✅ 已支援 |
| 數位簽名 | ❌ 不支援 | ✅ 已支援 |
| PDF/A合規性 | ❌ 不支援 | ✅ 已支援 |
快速入門:wkhtmltopdf 到IronPDF的遷移。
只要完成這些基本步驟,就可以立即開始遷移。
步驟 1:移除wkhtmltopdf套件和二進位檔案
移除所有wkhtmltopdfwrapper 套件:
# Removewkhtmltopdfwrapper (whichever you're using)
dotnet remove package WkHtmlToPdf-DotNet
dotnet remove package DinkToPdf
dotnet remove package TuesPechkin
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
dotnet remove package NReco.PdfGenerator
# Removewkhtmltopdfbinary from your deployment
# Delete wkhtmltopdf.exe, wkhtmltox.dll, etc.
# Removewkhtmltopdfwrapper (whichever you're using)
dotnet remove package WkHtmlToPdf-DotNet
dotnet remove package DinkToPdf
dotnet remove package TuesPechkin
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
dotnet remove package NReco.PdfGenerator
# Removewkhtmltopdfbinary from your deployment
# Delete wkhtmltopdf.exe, wkhtmltox.dll, etc.
步驟 2:安裝 IronPDF
# AddIronPDF(secure, modern alternative)
dotnet add package IronPdf
# AddIronPDF(secure, modern alternative)
dotnet add package IronPdf
步驟 3:更新命名空間
以IronPDF命名空間取代wkhtmltopdf命名空間:
// Before (wkhtmltopdf)
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
// After (IronPDF)
using IronPdf;
// Before (wkhtmltopdf)
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
// After (IronPDF)
using IronPdf;
' Before (wkhtmltopdf)
Imports WkHtmlToPdfDotNet
Imports WkHtmlToPdfDotNet.Contracts
' 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 方式之間的複雜性差異。
wkhtmltopdf 方法:
// 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 = 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 = 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
Imports WkHtmlToPdfDotNet
Imports WkHtmlToPdfDotNet.Contracts
Imports System.IO
Class Program
Shared Sub Main()
Dim converter = New SynchronizedConverter(New PdfTools())
Dim doc = New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = {
New ObjectSettings() With {
.HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("output.pdf", pdf)
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.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");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>")
pdf.SaveAs("output.pdf")
End Sub
End Class
wkhtmltopdf 需要建立一個 SynchronizedConverter,並使用 PdfTools 建構一個 HtmlToPdfDocument,使用 @@--CODE-20560--@@ 和 @@--CODE-20561--@@ 設定屬性,包括 @@--CODE-20562--@@、@@--CODE-20563--@@ 和 @@--CODE-20564--@@ 等,呼叫 @@--CODE-20565--@@ 取得原始位元組,並使用 @@--CODE-20566--@@ 手動寫入檔案。
IronPDF 完全消除了這種繁瑣的步驟——創建一個 ChromePdfRenderer,呼叫 RenderHtmlAsPdf(),然後使用內建的 SaveAs() 方法。
如需進階的 HTML 至IronPDF情境,請參閱 HTML 至 PDF 轉換指南。
將 URL 轉換為 PDF
URL 到 PDF 的轉換顯示出類似的複雜性模式。
wkhtmltopdf 方法:
// 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 = 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 = 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
Imports WkHtmlToPdfDotNet
Imports WkHtmlToPdfDotNet.Contracts
Imports System.IO
Module Program
Sub Main()
Dim converter As New SynchronizedConverter(New PdfTools())
Dim doc As New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = {
New ObjectSettings() With {
.Page = "https://www.example.com"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("webpage.pdf", pdf)
End Sub
End Module
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
wkhtmltopdf 使用 Page 屬性在 ObjectSettings 中指定 URL,需要相同的文檔建構模式。IronPDF提供了一個專門的 RenderUrlAsPdf() 方法,可以清楚地表達意圖。
探索URL至PDF文件的認證和自訂標頭選項。
自訂設定:具有頁面組態的 HTML 檔案
配置方向、邊界和紙張大小需要不同的方法。
wkhtmltopdf 方法:
// 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 = 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 = 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
Imports WkHtmlToPdfDotNet
Imports WkHtmlToPdfDotNet.Contracts
Imports System.IO
Class Program
Shared Sub Main()
Dim converter As New SynchronizedConverter(New PdfTools())
Dim doc As New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Landscape,
.PaperSize = PaperKind.A4,
.Margins = New MarginSettings() With {.Top = 10, .Bottom = 10, .Left = 10, .Right = 10}
},
.Objects = {
New ObjectSettings() With {
.Page = "input.html",
.WebSettings = New WebSettings() With {.DefaultEncoding = "utf-8"}
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("custom-output.pdf", pdf)
End Sub
End Class
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");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Class Program
Shared Sub Main()
Dim renderer As 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
Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
pdf.SaveAs("custom-output.pdf")
End Sub
End Class
wkhtmltopdf 將設定嵌套在 GlobalSettings 和 Objects 中,並將 MarginSettings 作為單獨的物件。IronPDF提供直接的 RenderingOptions 屬性,其名稱清晰明了,例如 PaperOrientation、MarginTop 和 PaperSize。
wkhtmltopdfAPI 到IronPDF的映射參考。
此對應可透過顯示直接的 API 對應關係來加速遷移:
CLI 到IronPDF的映射
| wkhtmltopdf CLI 選項 | IronPDF 同等級產品 |
|---|---|
wkhtmltopdf input.html output.pdf |
renderer.RenderHtmlFileAsPdf() |
wkhtmltopdf URL output.pdf |
renderer.RenderUrlAsPdf() |
--page-size A4 |
RenderingOptions.PaperSize = PdfPaperSize.A4 |
--page-size Letter |
RenderingOptions.PaperSize = PdfPaperSize.Letter |
--orientation Landscape |
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 |
--footer-center "[page]" |
{page}佔位符 |
--footer-center "[toPage]" |
{total-pages}佔位符 |
--enable-javascript |
預設啟用 |
--javascript-delay 500 |
RenderingOptions.WaitFor.RenderDelay = 500 |
--dpi 300 |
RenderingOptions.Dpi = 300 |
--grayscale |
RenderingOptions.GrayScale = true |
C# Wrapper API 對應。
| wkhtmltopdf Wrapper | IronPDF |
|---|---|
SynchronizedConverter |
ChromePdfRenderer |
HtmlToPdfDocument |
RenderingOptions |
GlobalSettings.Out |
pdf.SaveAs() |
GlobalSettings.PaperSize |
RenderingOptions.PaperSize |
GlobalSettings.Orientation |
RenderingOptions.PaperOrientation |
GlobalSettings.Margins |
RenderingOptions.Margin* |
ObjectSettings.Page |
RenderHtmlFileAsPdf() |
ObjectSettings.HtmlContent |
RenderHtmlAsPdf() |
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
};
// 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
};
' Before (wkhtmltopdf)
FooterSettings = New With {.Left = "Page [page] of [toPage]"}
' After (IronPDF)
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.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");
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");
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 Grid 和 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);
// 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);
Dim html As String = "
<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>"
Dim 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;
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
Imports System.Threading.Tasks
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Dim renderer As New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Function
wkhtmltopdf遷移清單
遷移前的任務
審核您的程式碼庫,找出所有wkhtmltopdf的用法:
# Find allwkhtmltopdfreferences
grep -r "WkHtmlToPdfDotNet\|DinkToPdf\|TuesPechkin\|Rotativa" --include="*.cs" .
grep -r "wkhtmltopdf" --include="*.yml" --include="*.yaml" --include="Dockerfile" .
# Find allwkhtmltopdfreferences
grep -r "WkHtmlToPdfDotNet\|DinkToPdf\|TuesPechkin\|Rotativa" --include="*.cs" .
grep -r "wkhtmltopdf" --include="*.yml" --include="*.yaml" --include="Dockerfile" .
找出並記錄wkhtmltopdf二進位檔案,以便移除。 文件目前的設定(紙張大小、邊界、頁首/頁腳)。
程式碼更新任務
1.移除所有wkhtmltopdfwrapper NuGet 套件 2.移除wkhtmltopdf的二進位檔 (wkhtmltopdf.exe, wkhtmltox.dll) 3.安裝IronPDFNuGet 套件
- 將命名空間導入從
WkHtmlToPdfDotNet更新為IronPdf - 將
SynchronizedConverter替換為ChromePdfRenderer - 將
HtmlToPdfDocument模式轉換為直接渲染方法 - 將
GlobalSettings配置更新為RenderingOptions - 將邊距配置從
MarginSettings轉換為單獨的屬性 - 更新佔位語法(
[page]→{page},[toPage]→{total-pages}) 10.在啟動時增加IronPDF授權初始化功能
後遷移測試
轉移後,驗證這些方面:
- PDF 輸出的視覺比較 (應使用現代 CSS 支援來改善)
- 驗證現代的 CSS 渲染(CSS Grid 和 Flexbox 現在可以使用)
- 測試 JavaScript 繁重的頁面
- 安全掃描以確認沒有wkhtmltopdf的二進位檔存在
- 性能比較的負載測試
安全性驗證
# Scan for any remainingwkhtmltopdfartifacts
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
# Scan for any remainingwkhtmltopdfartifacts
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
遷移到IronPDF的主要優點。
從wkhtmltopdf轉換到IronPDF提供了幾個關鍵優勢:
安全性: CVE-2022-35583 和所有wkhtmltopdf漏洞均已消除。IronPDF沒有已知的 CVE,並定期接受安全更新。
現代渲染引擎:IronPDF使用最新的 Chromium 引擎,確保完全支援 CSS3、CSS Grid、Flexbox 和 ES6+ JavaScript。 現代框架能正確呈現。
簡化 API:直接渲染方法取代文件建構模式。 內建的 SaveAs() 方法消除了手動位元組處理。
擴充功能: PDF 操作、數位簽章、PDF/A 合規性、浮水印和合併/分割操作是wkhtmltopdf無法提供的內建功能。
積極開發:隨著 .NET 10 和 C# 14 的普及,IronPDF 將持續更新,確保與目前和未來的 .NET 版本相容。
非同步支援:透過原生 async/await 支持,防止高負載 Web 應用程式中的執行緒阻塞。

