跳至頁尾內容
影片

如何在 C# | IronPDF 中新增目錄

wkhtmltopdf 一直是一個廣泛使用的工具,用於利用 Qt 4.8 + QtWebKit 將 HTML 文件轉換為 PDF。 儘管它在開發者中因為其命令行功能和免費授權而廣受歡迎,但該專案現在已產生無法忽視的關鍵安全風險。 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.6 2020年6月11日
底層引擎 Qt 4.8 + QtWebKit (Qt 4.8 在 2015 年結束支援) 已過時
CSS Grid 支援 None 已中斷
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"/>
HTML

當 wkhtmltopdf 渲染此 HTML 時,會從您伺服器的網路上下文中獲取這些 URL,從而繞過防火牆和安全控件。

受影響的封裝程式庫

每個 .NET 封裝都會捆綁或包裹同一個 wkhtmltopdf 本地二進制檔案,因此無論封裝程式庫本身的活動程度如何,它們都會繼承其 CVE 暴露:

封裝程式庫 最新 NuGet 安全風險
DinkToPdf 1.0.8 (2017年4月)— 已放棄 繼承 CVE-2022-35583
Rotativa.AspNetCore (webgio 分叉) 1.4.0 (2023年11月)— 封裝更新,二進制凍結 繼承 CVE-2022-35583
TuesPechkin 2.1.1 (2015年1月)— 已放棄 繼承 CVE-2022-35583
Haukcode.WkHtmlToPdfDotNet (以前是 WkHtmlToPdf-DotNet 1.5.95 (2024年10月) — 封裝更新,二進制凍結 繼承 CVE-2022-35583
NReco.PdfGenerator 封裝更新,捆綁 wkhtmltopdf 繼承 CVE-2022-35583

如果您使用了任何這些程式庫,那麼除非您清理所有 HTML 輸入,否則您的應用程式就暴露於 CVE-2022-35583。

IronPDFvs wkhtmltopdf:功能比較

了解結構差異有助於技術決策者評估遷移投資:

功能 wkhtmltopdf IronPDF
授權 LGPLv3 (免費) 商業
渲染引擎 Qt 4.8 + QtWebKit (Qt 4.8 在 2015 年結束支援) 當前的 Chromium 引擎
安全漏洞 CVE-2022-35583 (CVSS 9.8)未修補,有爭議 未報告關鍵 CVE
主動維護 GitHub 資源庫於 2023年1月2日被歸檔; 最後一次發布是 2020年6月 積極維護,定期發布
對現代 Web 標準的支援 有限(Flexbox 已中斷,無 CSS Grid) 支援
整合和支援 僅限於社區論壇 詳盡的文件和專門的支援
CSS Grid CSS 網格布局 ❌ 不支援 ✅ 支援
Flexbox ⚠ 已中斷 ✅ 支援
ES6+ JavaScript ❌ 不支援 ✅ 支援
Async/Await ❌ 不支援 ✅ 支援
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.
# 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
# AddIronPDF(secure, modern alternative)
dotnet add package IronPdf
SHELL

步驟 3:更新命名空間

用IronPDF命名空間替換 wkhtmltopdf 命名空間:

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

// After (IronPDF)
using IronPdf;
// Before (wkhtmltopdf)
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;

// After (IronPDF)
using IronPdf;
Imports IronPdf
$vbLabelText   $csharpLabel

步驟 4:初始化授權

在應用啓動時新增授權初始化:

IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

程式碼遷移範例

將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);
    }
}
// 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);
    }
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.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 List(Of ObjectSettings) From {
                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 Module
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

wkhtmltopdf 需要使用 SynchronizedConverter 建立 PdfTools,使用 GlobalSettingsObjects 構建 HtmlToPdfDocument,設置如 ColorMode, Orientation, 和 PaperSize 的屬性,調用 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);
    }
}
// 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);
    }
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.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 List(Of ObjectSettings) From {
                New ObjectSettings() With {
                    .Page = "https://www.example.com"
                }
            }
        }
        Dim pdf As Byte() = converter.Convert(doc)
        File.WriteAllBytes("webpage.pdf", pdf)
    End Sub
End Module
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

wkhtmltopdf 在 ObjectSettings 中使用 Page 屬性來指定 URL,需要相同的文件構建模式。IronPDF提供了一個專門的 RenderUrlAsPdf() 方法,清楚地表達意圖。

查看 URL 到 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);
    }
}
// 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);
    }
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.WkHtmlToPdfDotNet.Contracts
Imports System.IO

Module Program
    Sub Main()
        Dim converter = New SynchronizedConverter(New PdfTools())
        Dim doc = 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 Module
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

wkhtmltopdf 在 GlobalSettingsObjects 中巢狀設置,MarginSettings 作為單獨的物件。IronPDF提供了直接的 RenderingOptions 屬性,具有明確的名稱,如 PaperOrientation, MarginTop, 和 PaperSize

wkhtmltopdf API 到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# 封裝 API 映射

wkhtmltopdf 封裝 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
}
$vbLabelText   $csharpLabel

問題 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")
$vbLabelText   $csharpLabel

問題 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)
$vbLabelText   $csharpLabel

問題 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
$vbLabelText   $csharpLabel

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" .
# 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. 安裝IronPDFNuGet 套件
  4. 將命名空間導入從 Haukcode.WkHtmlToPdfDotNet (或您使用的封裝)更新到 IronPdf
  5. SynchronizedConverter 替換為 ChromePdfRenderer
  6. HtmlToPdfDocument 模式轉換為直接渲染方法
  7. GlobalSettings 配置更新為 RenderingOptions
  8. 將邊距配置從 MarginSettings 轉換為單一屬性
  9. 更新佔位符語法([page]{page}, [toPage]{total-pages}
  10. 在啟動時新增IronPDF授權初始化

遷移後測試

遷移後,驗證以下方面:

  • 視覺比較 PDF 輸出(應改進現代 CSS 支援)
  • 驗證現代 CSS 渲染(CSS Grid 和 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
# 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# 語言版本會在發佈時提供支援。

異步支援: 本地異步/等待支援可防止高負載網頁應用程式中的執行緒阻塞。

請注意DinkToPdf, NReco, Rotativa, TuesPechkin, 和 wkhtmltopdf 是其各自所有者的註冊商標。 此網站與 DinkToPdf、NReco、Rotativa、TuesPechkin 或 wkhtmltopdf 無關聯、未經認可或未得到贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供參考,反映撰寫時公開可用的資訊。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話