Haukcode.DinkToPdf與IronPDF:技術比較指南
當.NET開發者查看PDF生成選項時,Haukcode.DinkToPdf作為已停止的DinkToPdf專案的延續脫穎而出,它使用了wkhtmltopdf二進位檔。 雖然Haukcode.DinkToPdf提供基本的HTML轉PDF功能,但由於該專案已被放棄,來自wkhtmltopdf的重大安全風險將永遠不會被修復。 IronPDF提供了另一個選擇:一個使用現代Chromium引擎的積極維護的程式庫,並且定期進行安全更新。
此比較檢視了這兩個程式庫在相關技術方面的情況,以協助開發者和架構師做出明智的.NET PDF需求選擇。
探索Haukcode.DinkToPdf
Haukcode.DinkToPdf是曾經流行的DinkToPdf程式庫的延續,基於現在已不再開發的wkhtmltopdf二進位檔。 該程式庫旨在保持與.NET Core的相容,同時提供HTML轉PDF的轉換功能。 作為一個被放棄專案的延續,Haukcode.DinkToPdf存在顯著的限制。
Haukcode.DinkToPdf使用PdfTools進行轉換。 配置管理通過包含HtmlToPdfDocument對象進行管理。 byte[]數據。
該程式庫需要特定於平台的本機二進位檔:libwkhtmltox.dylib(macOS)。 由於wkhtmltopdf的限制,線程安全需要在單一模式下使用SynchronizedConverter。
探索IronPDF
IronPDF是使用現代Chromium渲染引擎獨立開發的.NET程式庫。這個程式庫由專業支援積極維護,並定期進行更新和安全修補。
IronPDF使用RenderingOptions屬性來進行配置。 類似BinaryData訪問。 該程式庫是自包含的,無需外部本機二進位檔,且設計上是線程安全的,並不需要單一模式。
關鍵的安全考量
這些程式庫之間最顯著的差異涉及安全性。 Haukcode.DinkToPdf繼承了CVE-2022-35583,一個帶有9.8 CVSS評分的嚴重服務器端請求偽造(SSRF)漏洞。
CVE-2022-35583 攻擊向量:
- 惡意HTML內容可以讓服務器獲取內部資源
- AWS元數據攻擊可以訪問
http://169.254.169.254來竊取憑證 - 內部網絡掃描及訪問內部服務
- 通過
file://協議的本地文件包裝 - 有可能完全接管基礎架構
這個漏洞沒有修復措施,因為wkhtmltopdf已被放棄(自2023年1月起歸檔,最後一次發行是在2020年的0.12.6)。
| 安全層面 | Haukcode.DinkToPdf | IronPDF |
|---|---|---|
| 關鍵CVE | CVE-2022-35583(CVSS 9.8,無法修復) | 積極修補 |
| 底層引擎 | wkhtmltopdf(Qt WebKit ~2015) | Chromium(定期更新) |
| 專案狀態 | 放棄專案的分支 | 積極開發 |
| 安全更新 | 不預期有 | 定期發布 |
| 支持 | 僅社群 | 專業支持 |
架構和引擎比較
基本的架構差異影響渲染質量、現代網絡標準支持和部署複雜性。
| 方面 | Haukcode.DinkToPdf | IronPDF |
|---|---|---|
| 渲染引擎 | Qt WebKit (~2015) | Chromium(當前) |
| HTML5/CSS3 | 有限 | 支持 |
| JavaScript | 有限制,且不安全 | 完整的V8引擎 |
| 本機二進位檔 | 需要(特定於平台) | 自包含 |
| 線程安全性 | 需要單一模式 | 設計上的線程安全 |
| 更新 | 不預期有 | 定期發布 |
由於依賴於過時的Qt WebKit引擎,Haukcode.DinkToPdf缺失數年的安全修補,並對現代網絡標準的支持有限。 IronPDF的Chromium引擎提供當前網絡標準支持及定期更新。
程式碼比較:常見的PDF操作
HTML到PDF的轉換
最基本的操作顯示了API設計的差異。
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);
}
}Imports DinkToPdf
Imports DinkToPdf.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.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = New List(Of ObjectSettings) From {
New ObjectSettings() With {
.HtmlContent = "<html><body><h1>Hello World</h1></body></html>"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("output.pdf", pdf)
End Sub
End ModuleIronPDF:
// 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");
}
}Imports IronPdf
Imports System.IO
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Hello World</h1></body></html>")
pdf.SaveAs("output.pdf")
End Sub
End ClassHaukcode.DinkToPdf需要創建一個包含File.WriteAllBytes()寫入磁碟。
IronPDF創建一個SaveAs()保存。 使用現代API設計的操作顯著更簡潔。
有關進階HTML渲染選項,請查看HTML到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);
}
}Imports DinkToPdf
Imports DinkToPdf.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.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 ModuleIronPDF:
// 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 ClassHaukcode.DinkToPdf使用相同的ObjectSettings.Page屬性指定URL。 IronPDF提供一個專門的RenderUrlAsPdf()方法,直接接受URL——對此特定用例而言是一個較為乾淨的API。
注意使用Haukcode.DinkToPdf的URL渲染存在CVE-2022-35583 SSRF漏洞風險,因為惡意URLs或重定向可能會利用該服務器。
自定義頁面設置
頁面配置顯示了不同的配置模型。
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);
}
}Imports DinkToPdf
Imports DinkToPdf.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.Letter,
.Margins = New MarginSettings() With {.Top = 10, .Bottom = 10, .Left = 10, .Right = 10}
},
.Objects = {
New ObjectSettings() With {
.HtmlContent = "<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("landscape.pdf", pdf)
End Sub
End ModuleIronPDF:
// 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");
}
}Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main()
Dim 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
Dim pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>")
pdf.SaveAs("landscape.pdf")
End Sub
End ClassHaukcode.DinkToPdf通過嵌套GlobalSettings進行頁面設定配置。 屬性使用類似PaperKind.Letter的枚舉。
IronPDF使用RenderingOptions屬性直接在渲染器上設定。 屬性可單獨設置(PaperSize, PaperOrientation, PdfPaperSize.Letter, PdfPaperOrientation.Landscape)。 雙方都使用毫米作為邊緣單位。
在IronPDF教程中了解更多有關渲染配置的資訊。
API映射參考
對於評估Haukcode.DinkToPdf遷移或功能比較的開發者而言,這種映對顯示了等效操作:
轉換器類映對
| Haukcode.DinkToPdf | IronPDF |
|---|---|
SynchronizedConverter | ChromePdfRenderer |
BasicConverter | ChromePdfRenderer |
PdfTools | 不適用 |
IConverter | 不適用 |
文檔配置映對
| Haukcode.DinkToPdf | IronPDF |
|---|---|
HtmlToPdfDocument | 方法調用 |
GlobalSettings | RenderingOptions |
ObjectSettings | RenderingOptions |
converter.Convert(doc) | renderer.RenderHtmlAsPdf(html) |
全局設定屬性映對
| 全局設定屬性 | IronPDF屬性 |
|---|---|
ColorMode | RenderingOptions.GrayScale |
Orientation | RenderingOptions.PaperOrientation |
PaperSize | RenderingOptions.PaperSize |
Margins.Top | RenderingOptions.MarginTop |
Margins.Bottom | RenderingOptions.MarginBottom |
Margins.Left | RenderingOptions.MarginLeft |
Margins.Right | RenderingOptions.MarginRight |
對象設置屬性映對
| 對象設置屬性 | IronPDF等效 |
|---|---|
HtmlContent | 第一個參數至RenderHtmlAsPdf() |
Page(URL) | renderer.RenderUrlAsPdf(url) |
HeaderSettings.Right = "[page]" | TextHeader.RightText = "{page}" |
占位符語法差異
頁首/頁尾占位符使用程式庫之間不同的語法:
| Haukcode.DinkToPdf | IronPDF |
|---|---|
[page] | {page} |
[toPage] | {total-pages} |
[date] | {date} |
線程安全與依賴注入
由於從wkhtmltopdf繼承的線程安全限制,Haukcode.DinkToPdf需要謹慎處理。
Haukcode.DinkToPdf(需要單一模式):
// Startup.cs - MUST be singleton due to thread safety issues
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
}// Startup.cs - MUST be singleton due to thread safety issues
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
}' Startup.vb - MUST be singleton due to thread safety issues
Public Sub ConfigureServices(services As IServiceCollection)
services.AddSingleton(GetType(IConverter), New SynchronizedConverter(New PdfTools()))
End SubIronPDF(靈活):
// Startup.cs - Can be singleton or transient (both work)
public void ConfigureServices(IServiceCollection services)
{
IronPdf.License.LicenseKey = Configuration["IronPdf:LicenseKey"];
services.AddSingleton<IPdfService, IronPdfService>();
// Or services.AddTransient<IPdfService, IronPdfService>() - both are safe!
}// Startup.cs - Can be singleton or transient (both work)
public void ConfigureServices(IServiceCollection services)
{
IronPdf.License.LicenseKey = Configuration["IronPdf:LicenseKey"];
services.AddSingleton<IPdfService, IronPdfService>();
// Or services.AddTransient<IPdfService, IronPdfService>() - both are safe!
}Imports Microsoft.Extensions.DependencyInjection
Public Sub ConfigureServices(services As IServiceCollection)
IronPdf.License.LicenseKey = Configuration("IronPdf:LicenseKey")
services.AddSingleton(Of IPdfService, IronPdfService)()
' Or services.AddTransient(Of IPdfService, IronPdfService) - both are safe!
End SubIronPDF在設計上是線程安全的,允許靈活的依賴注入模式,無需單一模式。
功能比較總結
| 功能 | Haukcode.DinkToPdf | IronPDF |
|---|---|---|
| 來源原點 | 放棄專案的分支 | 獨立開發 |
| 安全性 | 從上游繼承的CVE(無法修復) | 主動進行修補和安全 |
| 社群與支援 | 規模小且不固定 | 規模大且活躍,並有專門投入 |
| 功能與更新 | 有限且不固定 | 定期進行持續開發 |
| 多線程支持 | 需要單一模式 | 完全支持並優化 |
| 本機二進位檔 | 需要(特定於平台) | 自包含 |
| HTML5/CSS3 | 有限 | 支持 |
| JavaScript | 有限 | 完整的V8引擎 |
| 授權 | MIT(免費) | 商業的,免費試用 |
當團隊考慮從Haukcode.DinkToPdf轉向IronPDF
開發團隊評估從Haukcode.DinkToPdf轉向IronPDF有以下幾個原因:
關鍵安全漏洞: CVE-2022-35583(SSRF)是一個CVSS 9.8的嚴重漏洞,永遠無法修補。 對於處理用戶提供的HTML或渲染外部URL的應用程式,這個漏洞可以竊取AWS憑證、訪問內部網絡以及本地文件包裝攻擊。
放棄的底層技術: wkhtmltopdf已被放棄(2023年1月歸檔,最後更新於2020年)。 作為延續的Haukcode.DinkToPdf無法解決底層技術的基本問題。 過時的Qt WebKit引擎(~2015)錯過了多年的安全修補。
本機二進制管理: Haukcode.DinkToPdf需要分發特定平臺的二進制檔案(libwkhtmltox.dylib)。 這使得部署、CI/CD管道和容器化更為複雜。 IronPDF是自包含的,無需外部二進位檔。
線程安全限制: 必須的SynchronizedConverter單一模式限制了架構靈活性,並且在負載下可能形成瓶頸。 IronPDF在設計上是線程安全的,允許按請求實例。
現代網頁標準: 有限的HTML5/CSS3支持和不安全的JavaScript執行限制了現代網絡內容的渲染能力。 IronPDF的Chromium引擎提供當前網頁標準的支持。
長期生命週期: 依賴被放棄的技術會隨時間推移而產生技術負擔。隨著項目向.NET 10和C# 14方向擴展到2026年,維持對未經維護的wkhtmltopdf包裝程式的依賴將愈加問題重重。
優勢和考量
Haukcode.DinkToPdf的優勢
- 免費和開源: MIT許可證,無許可費用
- 基本功能: 支持基本的HTML轉PDF轉換
- 已有的代碼庫: 對於已經使用DinkToPdf的團隊已經很熟悉
Haukcode.DinkToPdf的考量
- 嚴重的安全漏洞: CVE-2022-35583無法修復
- 被放棄的技術: 構建在已停止的wkhtmltopdf之上
- 依賴於本機二進位檔: 需要特定於平臺的DLL
- 線程安全問題: 需要單一模式
- 有限的網頁標準: 過時的Qt WebKit引擎
- 沒有專業支持: 只能依靠社群協助
- 技術負擔: 對被放棄專案的依賴增加了風險
IronPDF的優勢
IronPDF的考量
- 商業授權:生產使用需要商業授權
結論
Haukcode.DinkToPdf和IronPDF代表了.NET應用程式中生成PDF的兩種根本不同的方法。 Haukcode.DinkToPdf作為被放棄的DinkToPdf專案的延續,其中包裝了已停止支援的wkhtmltopdf二進位檔,帶有關鍵安全漏洞(CVE-2022-35583)永遠無法修補。 該程式庫需要本機二進位檔分發、單一模式以確保線程安全,並且有限的現代網絡標準支援。
IronPDF提供了一個積極維護的替代選項,具有現代的Chromium引擎,定期的安全更新和線程安全的架構。 該自提供的程式庫消除了本機二進位檔管理,並提供完全的HTML5/CSS3/JavaScript支持。
當組織計畫.NET 10、C# 14開發以及2026年前的應用程式開發時,在保持依賴不被維護的技術存在關鍵不可修復漏洞與採用積極維護的解決方案並具有現代功能之間的選擇顯著影響安全狀態和開發速度。 需要安全PDF生成、現代渲染或簡化部署的團隊會發現IronPDF高效地滿足這些要求。
開始評估IronPDF,通過免費試用,並查看更多詳細文檔,來評估其對您的具體需求是否合適。
