影片

如何使用 C# 將 DOCX 轉換為 PDF

Curtis Chau
Curtis Chau
Updated: 2026年5月18日

Haukcode.DinkToPdf 是曾經流行的 DinkToPdf 程式庫的一個社區分支,它包裝了 wkhtmltopdf 二進位檔,以便於 .NET 應用程式中的 HTML 到 PDF 轉換。 該分支後來更名為 Haukcode.WkHtmlToPdfDotNet,最新版本 1.5.95 於 2024 年 10 月 22 日發布,遵循 LGPL-3.0-or-later 授權。 儘管此分支在原始 DinkToPdf (1.0.8,2017 年 4 月 18 日)被棄用後,仍在 NuGet 上保留了這個套件,但它仍然綁定於與其父類相同的存檔 wkhtmltopdf 二進位檔。 wkhtmltopdf/wkhtmltopdf 倉庫於 2023 年 1 月 2 日被存檔, 整個 wkhtmltopdf GitHub 組織於 2024 年 7 月 10 日被存檔,因此上游問題將不會被修補。

這份指南提供了一條從 Haukcode.DinkToPdf / Haukcode.WkHtmlToPdfDotNet 遷移到IronPDF的路徑,包括逐步指南、程式碼比較以及適用於 .NET 開發者的實用範例,以幫助他們在從存檔的 wkhtmltopdf 二進位檔移除時使用。

安全建議:CVE-2022-35583

Haukcode.DinkToPdf 繼承了一個針對其上游 wkhtmltopdf 二進位檔發佈的安全建議:

CVE-2022-35583 - 針對 wkhtmltopdf 0.12.6 的 SSRF 建議

針對 wkhtmltopdf 0.12.6 的伺服器端請求偽造建議已經發布(NVD 中的 CVSS 9.8); 被上游 wkhtmltopdf 專案質疑,認為這是一個應用程式端的輸入清理問題,而不是一個程式庫錯誤。 無論哪種方式,這都不會被修補——上游已被存檔。 在公共討論中,典型的曝光模式包括:

  • 攻擊途徑: 未受信任的 HTML 內容可能會導致渲染器在轉換時獲取內部資源
  • AWS Metadata: 如果渲染器在 EC2 上運行,向 http://169.254.169.254 請求可能會返回實例元資料
  • 內部網路存取: 渲染主機可能可以存取內部服務
  • 本地文件包含: 透過 file:// 協議本地文件可能是可讀的

不期望上游修補 - wkhtmltopdf 倉庫於 2023 年 1 月 2 日被存檔,最後一次發布(0.12.6)是在 2020 年 6 月。

##IronPDF與 Haukcode.DinkToPdf:功能比較

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

方面Haukcode.DinkToPdfIronPDF
基礎引擎wkhtmltopdf (QtWebKit 分支,大約 2015 年)現代 Chromium
安全狀態CVE-2022-35583 建議(未修補/上游被質疑)無已知的關鍵 CVE
專案狀態社區分支; 上游 wkhtmltopdf 被存檔積極維護
HTML5/CSS3沒有現代 Flexbox/Grid完整支持 CSS3
JavaScript有限且不一致的支持全面支持
原生二進位檔libwkhtmltox.dll/.so/.dylib 每個平台以 NuGet 套件管理
執行緒安全SynchronizedConverter 序列化呼叫設計上具現成的執行緒安全性
支援社區支持專業支持
更新分支最新發佈1.5.95(2024年10月22日); 上游 wkhtmltopdf 0.12.6(2020 年 6 月)定期發布
授權LGPL-3.0-or-later(fork) / MIT(原始 DinkToPdf)商業授權,提供免費試用

快速開始:Haukcode.DinkToPdf 遷移到 IronPDF

可以立即透過這些基本步驟開始遷移。

步驟 1:移除 DinkToPdf 和原生二進位檔

移除 Haukcode.DinkToPdf NuGet 套件:

# Remove NuGet packages
dotnet remove package DinkToPdf
dotnet remove package Haukcode.DinkToPdf
dotnet remove package Haukcode.WkHtmlToPdf-DotNet
SHELL

從專案中刪除原生二進位檔:

  • libwkhtmltox.dll(Windows)
  • libwkhtmltox.so(Linux)
  • libwkhtmltox.dylib(macOS)

步驟 2:安裝 IronPDF

# Install IronPDF
dotnet add package IronPdf
SHELL

步驟 3:更新命名空間

將 DinkToPdf 命名空間替換為 IronPDF:

// Before (Haukcode.DinkToPdf)
using DinkToPdf;
using DinkToPdf.Contracts;

// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;  // For RenderingOptions

步驟 4:初始化授權

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

IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

程式碼遷移範例

基本 HTML 到 PDF 轉換

最基本的操作揭示了這些 .NET PDF 程式庫之間的複雜性差異。

Haukcode.DinkToPdf 方法:

// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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 = "<html><body><h1>Hello World</h1></body></html>",
                }
            }
        };
        
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("output.pdf", pdf);
    }
}

IronPDF 方法:

// NuGet: Install-Package IronPdf
using IronPdf;
using System.IO;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        
        var pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Hello World</h1></body></html>");
        
        pdf.SaveAs("output.pdf");
    }
}

Haukcode.DinkToPdf 需要使用 SynchronizedConverter 和 PdfTools 建立一個 HtmlToPdfDocument,使用巢狀的 GlobalSettings 和 Objects 構建一個 ObjectSettings,使用 HtmlContent 新增一個 converter.Convert() 以獲取原始位元組,並使用 File.WriteAllBytes() 手動寫入文件。

IronPDF 將此簡化為三行:建立 ChromePdfRenderer,調用 RenderHtmlAsPdf(),並使用內建的 SaveAs() 方法。

如需進階 HTML 到 PDF 的場景,請參見 HTML 到 PDF 轉換指南。

將 URL 轉換為 PDF

URL-to-PDF 轉換顯示了類似的模式差異。

Haukcode.DinkToPdf 方法:

// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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");
    }
}

Haukcode.DinkToPdf 使用相同的文件構建模式,加上 ObjectSettings.Page 構造 URL。IronPDF提供了一個專用的 RenderUrlAsPdf() 方法,明確表達意圖。

查看 URL 到 PDF 文件,了解認證和自定義標頭選項。

自定義頁面設置

配置方向、紙張大小和邊距需要不同方式。

Haukcode.DinkToPdf 方法:

// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.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.Letter,
                Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
            },
            Objects = {
                new ObjectSettings() {
                    HtmlContent = "<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>",
                }
            }
        };
        
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("landscape.pdf", pdf);
    }
}

IronPDF 方法:

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        
        renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 10;
        renderer.RenderingOptions.MarginRight = 10;
        
        var pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>");
        
        pdf.SaveAs("landscape.pdf");
    }
}

Haukcode.DinkToPdf 在 GlobalSettings 內嵌設置,並有一個獨立的 MarginSettings 物件。IronPDF提供直接 RenderingOptions 屬性,如 PaperOrientation 和單獨的邊距屬性。

Haukcode.DinkToPdf API 到IronPDF映射參考

此映射透過展示直接的 API 等價加速遷移:

Converter 類映射

Haukcode.DinkToPdfIronPDF
SynchronizedConverterChromePdfRenderer
BasicConverterChromePdfRenderer
PdfTools無
IConverter無

文件配置映射

Haukcode.DinkToPdfIronPDF
HtmlToPdfDocument方法調用
GlobalSettingsRenderingOptions
ObjectSettingsRenderingOptions
converter.Convert(doc)renderer.RenderHtmlAsPdf(html)

GlobalSettings 屬性映射

GlobalSettings 屬性IronPDF 屬性
ColorModeRenderingOptions.GrayScale
OrientationRenderingOptions.PaperOrientation
PaperSizeRenderingOptions.PaperSize
Margins.TopRenderingOptions.MarginTop
Margins.BottomRenderingOptions.MarginBottom
Margins.LeftRenderingOptions.MarginLeft
Margins.RightRenderingOptions.MarginRight

ObjectSettings 屬性映射

ObjectSettings 屬性IronPDF等價
HtmlContent第一個參數至 RenderHtmlAsPdf()
Page (URL)renderer.RenderUrlAsPdf(url)
HeaderSettings.Right = "[page]"{page} 在 HtmlHeader.HtmlFragment 內

佔位符語法遷移

Haukcode.DinkToPdfIronPDF
[page]{page}
[toPage]{total-pages}
[date]{date}

常見遷移問題及解決方案

問題1:單例要求

Haukcode.DinkToPdf: 由於原生 wkhtmltopdf 二進位檔的執行緒安全問題,要求 SynchronizedConverter 作為單例。

解決方案:IronPDF的 ChromePdfRenderer 具有設計上的執行緒安全性,不需要單例:

// Before (DinkToPdf) - MUST be singleton
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

// After (IronPDF) - Can be singleton or transient (both work)
services.AddSingleton<IPdfService, IronPdfService>();
// Or services.AddTransient<IPdfService, IronPdfService>() - both are safe!

問題2:原生二進位檔案依賴

Haukcode.DinkToPdf: 需要平台特定的原生庫(libwkhtmltox.dll/so/dylib)。

解決方案:IronPDF是自包含的,無需原生二進位檔依賴。 遷移後刪除這些文件:

  • libwkhtmltox.dll(Windows)
  • libwkhtmltox.so(Linux)
  • libwkhtmltox.dylib(macOS)

問題3:返回型別差異

Haukcode.DinkToPdf: converter.Convert() 直接返回 byte[]。

解決方案:IronPDF返回一個 PdfDocument 物件,具有多種輸出選項:

var pdf = renderer.RenderHtmlAsPdf(html);
byte[] bytes = pdf.BinaryData;  // Get bytes
pdf.SaveAs("output.pdf");       // Or save directly

問題4:頁眉/頁腳佔位符語法

Haukcode.DinkToPdf: 使用方括號語法,如 [page] 和 [toPage]。

解決方案: 更新為IronPDF的大括號佔位符:

// Before (DinkToPdf)
HeaderSettings = { Right = "Page [page] of [toPage]" }

// After (IronPDF)
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<span style='float:right'>Page {page} of {total-pages}</span>"
};

Haukcode.DinkToPdf 遷移檢查清單

遷移前任務

審核您的程式碼基礎,以識別所有 DinkToPdf 的使用情況:

# Find DinkToPdf namespace usage
grep -r "using DinkToPdf\|using Haukcode" --include="*.cs" .

# Find converter usage
grep -r "SynchronizedConverter\|BasicConverter\|HtmlToPdfDocument" --include="*.cs" .

# Find native library loading
grep -r "wkhtmltopdf\|libwkhtmltox" --include="*.cs" --include="*.csproj" .

# Find GlobalSettings/ObjectSettings usage
grep -r "GlobalSettings\|ObjectSettings\|MarginSettings" --include="*.cs" .
SHELL

記錄當前 GlobalSettings 和 ObjectSettings 配置。 找出可以刪除的任何原生庫載入程式碼。

程式碼更新任務

  1. 移除 DinkToPdf NuGet 套件
  2. 安裝IronPDFNuGet 套件
  3. 將名稱空間導入從 DinkToPdf 更新到 IronPdf
  4. 將 SynchronizedConverter 替換為 ChromePdfRenderer
  5. 將 HtmlToPdfDocument 模式轉換為直接方法調用
  6. 將 GlobalSettings 轉換為 RenderingOptions
  7. 將 ObjectSettings 轉換為 RenderingOptions
  8. 更新佔位符語法([page] → {page}, [toPage] → {total-pages})
  9. 在啟動時新增IronPDF授權初始化

基礎設施清理任務

  1. 刪除原生二進位檔(libwkhtmltox.*)
  2. 移除原生庫載入程式碼
  3. 如果存在,移除 CustomAssemblyLoadContext
  4. 更新依賴註入(不再需要單例)
  5. 移除用於原生二進位檔的平臺檢測程式碼

遷移後測試

遷移後,驗證以下方面:

  • 測試 HTML 到 PDF 的轉換
  • 測試 URL 到 PDF 的轉換
  • 驗證頁面設置(大小、方向、邊距)
  • 驗證帶佔位符的頁眉和頁腳
  • 使用實際 HTML 模板進行測試
  • 在負載下進行性能測試

遷移到IronPDF的關鍵好處

從 Haukcode.DinkToPdf 遷移到IronPDF提供了幾個關鍵優勢:

安全性: 消除了 CVE-2022-35583(SSRF)和其他 wkhtmltopdf 漏洞,這些漏洞永遠不會被修補。

現代渲染引擎: 使用積極更新的 Chromium 而不是 2015 年的棄用 Qt WebKit。 完整 HTML5、CSS3 和 JavaScript 支持。

無原生二進位檔: 自包含的程式庫,無需管理平台特定的 DLL。 簡化在 Windows、Linux 和 macOS 上的部署。

執行緒安全性: 無需單例要求 - 在任何模式(包括每個請求實例化)中自由使用 ChromePdfRenderer。

簡化的 API: 直接方法調用(RenderHtmlAsPdf(), RenderUrlAsPdf()),而不是複雜的文件物件構建。

積極開發:IronPDF的定期發布節奏使得它與當前 .NET 版本(包括 .NET Framework 4.6.2+、.NET Core 3.1+、和 .NET 5/6/7/8/9/10)相容。

請注意: DinkToPdf、Haukcode.DinkToPdf、Haukcode.WkHtmlToPdfDotNet 和 wkhtmltopdf 是其各自擁有者的商標或產品名稱。 本網站與這些項目中的任何一個都沒有聯繫、背書或贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供參考,反映撰寫時公開可用的資訊。

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

閱讀更多

相關文章