比較

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.DinkToPdfIronPDF
關鍵CVECVE-2022-35583(CVSS 9.8,無法修復)積極修補
底層引擎wkhtmltopdf(Qt WebKit ~2015)Chromium(定期更新)
專案狀態放棄專案的分支積極開發
安全更新不預期有定期發布
支持僅社群專業支持

架構和引擎比較

基本的架構差異影響渲染質量、現代網絡標準支持和部署複雜性。

方面Haukcode.DinkToPdfIronPDF
渲染引擎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 Module
$vbLabelText   $csharpLabel

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");
    }
}
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 Class
$vbLabelText   $csharpLabel

Haukcode.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 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

Haukcode.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 Module
$vbLabelText   $csharpLabel

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");
    }
}
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 Class
$vbLabelText   $csharpLabel

Haukcode.DinkToPdf通過嵌套GlobalSettings進行頁面設定配置。 屬性使用類似PaperKind.Letter的枚舉。

IronPDF使用RenderingOptions屬性直接在渲染器上設定。 屬性可單獨設置(PaperSize, PaperOrientation, PdfPaperSize.Letter, PdfPaperOrientation.Landscape)。 雙方都使用毫米作為邊緣單位。

IronPDF教程中了解更多有關渲染配置的資訊。

API映射參考

對於評估Haukcode.DinkToPdf遷移或功能比較的開發者而言,這種映對顯示了等效操作:

轉換器類映對

Haukcode.DinkToPdfIronPDF
SynchronizedConverterChromePdfRenderer
BasicConverterChromePdfRenderer
PdfTools不適用
IConverter不適用

文檔配置映對

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

全局設定屬性映對

全局設定屬性IronPDF屬性
ColorModeRenderingOptions.GrayScale
OrientationRenderingOptions.PaperOrientation
PaperSizeRenderingOptions.PaperSize
Margins.TopRenderingOptions.MarginTop
Margins.BottomRenderingOptions.MarginBottom
Margins.LeftRenderingOptions.MarginLeft
Margins.RightRenderingOptions.MarginRight

對象設置屬性映對

對象設置屬性IronPDF等效
HtmlContent第一個參數至RenderHtmlAsPdf()
Page(URL)renderer.RenderUrlAsPdf(url)
HeaderSettings.Right = "[page]"TextHeader.RightText = "{page}"

占位符語法差異

頁首/頁尾占位符使用程式庫之間不同的語法:

Haukcode.DinkToPdfIronPDF
[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 Sub
$vbLabelText   $csharpLabel

IronPDF(靈活):

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

IronPDF在設計上是線程安全的,允許靈活的依賴注入模式,無需單一模式。

功能比較總結

功能Haukcode.DinkToPdfIronPDF
來源原點放棄專案的分支獨立開發
安全性從上游繼承的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的優勢

  • 主動的安全修補: 定期更新解決漏洞
  • 現代的Chromium引擎: 多現代網頁標準支持
  • 自包含: 無本機二進位檔依賴
  • 線程安全設計: 靈活的部署模式
  • 完整的HTML5/CSS3/JavaScript: 現代渲染能力
  • 專業支援: 專寫的工程支援
  • 全面資源:豐富的教程文檔

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,通過免費試用,並查看更多詳細文檔,來評估其對您的具體需求是否合適。

請注意DinkToPdf 和 wkhtmltopdf 是其各自所有者的註冊商標。 本站與 DinkToPdf 或 wkhtmltopdf 沒有關聯、認可或贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供信息之用,並反映撰寫時的公開信息。)}]