從 Haukcode.DinkToPdf 遷移到 IronPDF
Haukcode.DinkToPdf 是曾經流行的 DinkToPdf 庫的延續,它使用 wkhtmltopdf 二進位檔案將 HTML 轉換為 PDF,供 .NET 應用程式使用。 儘管 Haukcode.DinkToPdf 在原始專案停滯後繼續支援 .NET Core,但它由於其上游依賴項而存在嚴重的安全性問題。 wkhtmltopdf 專案已於 2023 年 1 月存檔,因此這些問題將永遠無法解決。
本指南提供了從 Haukcode.DinkToPdf 到 IronPDF 的完整遷移路徑,包括逐步說明、程式碼比較和實用範例,旨在幫助專業的 .NET 開發人員消除 PDF 生成工作流程中的安全風險。
嚴重安全警告:CVE-2022-35583
Haukcode.DinkToPdf 從 wkhtmltopdf 繼承了一個無法解決的重大安全漏洞:
CVE-2022-35583 - 嚴重 SSRF 漏洞 (CVSS 9.8)
wkhtmltopdf 庫(以及所有封裝庫,包括 Haukcode.DinkToPdf)存在伺服器端請求偽造 (SSRF) 漏洞:
攻擊途徑:惡意 HTML 內容可導致伺服器取得內部資源。
- AWS 元資料攻擊:可存取
http://169.254.169.254竊取 AWS 憑證 -內部網路存取:可掃描和存取內部服務 -本機檔案包含:可透過file://協定讀取本機文件 影響:可能完全接管基礎設施
由於 wkhtmltopdf 已於 2023 年停止維護並存檔,因此漏洞無法修復。其最後一個版本是 2020 年發布的 0.12.6 版本。
IronPDF 與 Haukcode.DinkToPdf:功能對比
了解架構差異有助於技術決策者評估遷移投資:
| 方面 | Haukcode.DinkToPdf | IronPDF |
|---|---|---|
| 底層引擎 | wkhtmltopdf(Qt WebKit ~2015) | Chromium(定期更新) |
| 安全狀態 | CVE-2022-35583(嚴重,無法修復) | 已積極打補丁 |
| 專案狀態 | 廢棄項目的分支 | 積極開發 |
| HTML5/CSS3 | 有限的 | 全力支持 |
| JavaScript | 有限、不安全 | 全V8發動機 |
| 本地二進位文件 | 必需(平台特定) | 自給自足 |
| 螺紋安全 | 需要單例模式 | 螺紋安全設計 |
| 支援 | 僅限社區 | 專業支援 |
| 更新 | 預計不會發生 | 定期發布 |
| 執照 | 麻省理工學院(免費) | 提供免費試用的商業廣告 |
快速入門: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# Remove NuGet packages
dotnet remove package DinkToPdf
dotnet remove package Haukcode.DinkToPdf
dotnet remove package Haukcode.WkHtmlToPdf-DotNet從專案中刪除本地二進位檔案:
libwkhtmltox.dll(Windows)libwkhtmltox.so(Linux)libwkhtmltox.dylib(macOS)
步驟 2:安裝 IronPDF
# Install IronPDF
dotnet add package IronPdf# Install IronPDF
dotnet add package IronPdf步驟 3:更新命名空間
將 DinkToPdf 命名空間替換為 IronPdf:
// Before (Haukcode.DinkToPdf)
using DinkToPdf;
using DinkToPdf.Contracts;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering; // For RenderingOptions// Before (Haukcode.DinkToPdf)
using DinkToPdf;
using DinkToPdf.Contracts;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering; // For RenderingOptions步驟 4:初始化許可證
在應用程式啟動時新增許可證初始化:
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";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);
}
}// 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");
}
}// 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 需要使用PdfTools建立一個SynchronizedConverter ,使用巢狀的GlobalSettings和Objects建構一個HtmlToPdfDocument ,加入一個帶有HtmlContent的ObjectSettings ,呼叫converter.Convert()取得原始位元組,然後使用File.WriteAllBytes() 。
IronPDF 將此簡化為三行程式碼:建立一個ChromePdfRenderer ,呼叫RenderHtmlAsPdf() ,然後使用內建的SaveAs()方法。
如需更進階的 HTML 轉 PDF 場景,請參閱HTML 轉 PDF 轉換指南。
將 URL 轉換為 PDF
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.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 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");
}
}// 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()方法,可以清楚地表達意圖。
查看指向 PDF 文件的 URL ,以了解身份驗證和自訂標頭選項。
自訂頁面設定
配置方向、紙張尺寸和頁邊距需要不同的方法。
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);
}
}// 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");
}
}// 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屬性,其名稱清晰明了,例如PaperSize 、 PaperOrientation和單獨的邊距屬性。
Haukcode.DinkToPdf API 到 IronPDF 映射參考
此映射透過顯示直接的 API 等效項來加速遷移:
轉換器類別映射
| Haukcode.DinkToPdf | IronPDF | 筆記 |
|---|---|---|
SynchronizedConverter | ChromePdfRenderer | 線程安全,無需單例模式 |
BasicConverter | ChromePdfRenderer | 同一個類別處理這兩個問題 |
PdfTools | 不適用 | 不需要 |
IConverter | 不適用 | 直接使用渲染器 |
文檔配置映射
| Haukcode.DinkToPdf | IronPDF | 筆記 |
|---|---|---|
HtmlToPdfDocument | 方法調用 | 直接使用RenderHtmlAsPdf() |
GlobalSettings | RenderingOptions | 設定渲染前 |
ObjectSettings | RenderingOptions | 合併成一個 |
converter.Convert(doc) | renderer.RenderHtmlAsPdf(html) | 返回PdfDocument |
全域設定屬性映射
| 全域設定屬性 | IronPDF屬性 | 筆記 |
|---|---|---|
ColorMode | RenderingOptions.GrayScale | 布林值,設定為true表示灰階模式 |
Orientation | RenderingOptions.PaperOrientation | Portrait或Landscape |
PaperSize | RenderingOptions.PaperSize | 使用PdfPaperSize枚舉 |
Margins.Top | RenderingOptions.MarginTop | 單位:毫米 |
Margins.Bottom | RenderingOptions.MarginBottom | 單位:毫米 |
Margins.Left | RenderingOptions.MarginLeft | 單位:毫米 |
Margins.Right | RenderingOptions.MarginRight | 單位:毫米 |
物件設定屬性映射
| ObjectSettings 屬性 | IronPDF當量 | 筆記 |
|---|---|---|
HtmlContent | RenderHtmlAsPdf()函數的第一個參數 | 直接參數 |
Page (URL) | renderer.RenderUrlAsPdf(url) | 單獨方法 |
HeaderSettings.Right = "[page]" | TextHeader.RightText = "{page}" | 不同的佔位符語法 |
佔位符語法遷移
| Haukcode.DinkToPdf | IronPDF | 筆記 |
|---|---|---|
[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!// 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 directlyvar 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.TextHeader = new TextHeaderFooter
{
RightText = "Page {page} of {total-pages}"
};// Before (DinkToPdf)
HeaderSettings = { Right = "Page [page] of [toPage]" }
// After (IronPDF)
renderer.RenderingOptions.TextHeader = new TextHeaderFooter
{
RightText = "Page {page} of {total-pages}"
};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" .# 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" .記錄目前的GlobalSettings和ObjectSettings配置。 找出所有可以刪除的本機庫載入程式碼。
程式碼更新任務
- 刪除 DinkToPdf NuGet 套件
- 安裝 IronPdf NuGet 套件
- 將命名空間導入從
DinkToPdf更新為IronPdf - 將
SynchronizedConverter替換為ChromePdfRenderer - 將
HtmlToPdfDocument模式轉換為直接方法調用 - 將
GlobalSettings轉換為RenderingOptions - 將
ObjectSettings轉換為RenderingOptions - 更新佔位符語法(
[page]→{page},[toPage]→{total-pages}) - 新增 IronPDF 啟動時許可證初始化功能
基礎設施清理任務
- 刪除本機二進位(libwkhtmltox.*)
- 移除本機庫載入程式碼
- 如果存在,則移除 CustomAssemblyLoadContext。
- 更新依賴注入(不再需要單例模式)
- 移除本地二進位檔案的平台偵測程式碼
遷移後測試
遷移完成後,請確認以下幾個面向:
- 測試 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() ),而不是複雜的文檔物件建構。
積極開發:隨著 .NET 10 和 C# 14 的普及,IronPDF 將持續更新,確保與目前和未來的 .NET 版本相容。






