比較

Haukcode.DinkToPdf vs 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 使用SynchronizedConverterPdfTools進行轉換。 配置透過HtmlToPdfDocument物件進行管理,該物件包含用於頁面選項(ColorMode、Orientation、PaperSize、Margins)的GlobalSettings和用於內容(HtmlContent 用於 HTML 字串,Page 用於 URL)的ObjectSettingsconverter.Convert(doc)方法返回原始 byte[] 資料。

該函式庫需要特定平台的本機二進位檔:libwkhtmltox.dll (Windows), libwkhtmltox.so (Linux), 和 libwkhtmltox.dylib (macOS). 由於 wkhtmltopdf 的限制,線程安全要求在單例模式下使用SynchronizedConverter

探索鐵質PDF

IronPDF 是一個獨立開發的 .NET 函式庫,使用現代的 Chromium 演算引擎。該函式庫透過定期更新、專業支援和持續的安全修補程式進行積極的維護。

IronPDF 使用<代碼>ChromePdfRenderer</代碼作為其主要的渲染類別,並透過渲染選項屬性進行設定。 像 RenderHtmlAsPdf()RenderUrlAsPdf() 之類的方法會返回 PdfDocument 物件,這些物件可以用 SaveAs() 儲存或以 BinaryData 存取。 這個函式庫是獨立的,不需要外部的原生二進位檔,而且在設計上是線程安全的,不需要單件模式。

關鍵的安全性考量

這些函式庫最顯著的差異在於安全性。 Haukcode.DinkToPdf 繼承了 CVE-2022-35583,這是一個重要的伺服器端請求偽造 (SSRF) 漏洞,CVSS 得分為 9.8。

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 引擎
原生二進位必需(特定平台)自成一格
線程安全需要單元模式線程安全的設計
更新無預期定期發佈

Haukcode.DinkToPdf 依賴於過時的 Qt WebKit 引擎,這意味著會錯過多年的安全修補程式,且對現代網頁標準的支援有限。IronPDF的 Chromium 引擎可定期更新,提供當前的 Web 標準支援。

程式碼比較:常見的 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);
    }
}
$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");
    }
}
$vbLabelText   $csharpLabel

Haukcode.DinkToPdf需要使用PdfTools建立一個SynchronizedConverter,用嵌套的GlobalSettingsObjectSettings物件建構一個HtmlToPdfDocument,呼叫Convert()取得原始位元組,然後用File.WriteAllBytes()手動寫入磁碟。WriteAllBytes()。

IronPDF 創建一個<代碼>ChromePdfRenderer</代碼,直接使用 HTML 字串呼叫 RenderHtmlAsPdf() ,並使用 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);
    }
}
$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");
    }
}
$vbLabelText   $csharpLabel

Haukcode.DinkToPdf 使用與 ObjectSettings.Page 屬性相同的<編碼>HtmlToPdfDocument</編碼結構來指定 URL。IronPDF提供了一個專用的 RenderUrlAsPdf() 方法,可直接接受 URL--對於此特定用例而言,這是一個更乾淨的 API。

請注意,使用 Haukcode.DinkToPdf 的 URL 渲染會帶有 CVE-2022-35583 SSRF 漏洞風險,因為惡意 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);
    }
}
$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");
    }
}
$vbLabelText   $csharpLabel

Haukcode.DinkToPdf 透過嵌套 MarginSettings 物件的全局設定來設定頁面設定。 屬性使用諸如 Orientation.LandscapePaperKind.Letter 之類的枚數。

IronPdf 直接在渲染器上使用渲染選項屬性。 屬性可個別設定 (PaperSizePaperOrientationMarginTop 等) 與類型化的枚舉 (PdfPaperSize.LetterPdfPaperOrientation.Landscape)。 兩者都使用毫米作為邊界單位。

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

API 對應參考。

對於評估 Haukcode.DinkToPdf 遷移或比較功能的開發人員而言,此對應圖顯示等效的操作:

轉換器類別對應

Haukcode.DinkToPdfIronPDF
同步轉換器<代碼>ChromePdfRenderer</代碼
基本轉換器<代碼>ChromePdfRenderer</代碼
<編碼>PdfTools</編碼不適用
IConverter不適用

文件配置映射

Haukcode.DinkToPdfIronPDF
<編碼>HtmlToPdfDocument</編碼方法調用
全局設定渲染選項
物件設定渲染選項
converter.Convert(doc)renderer.RenderHtmlAsPdf(html)

GlobalSettings 屬性對應

GlobalSettings 屬性IronPdf 特性
<編碼>ColorMode</編碼RenderingOptions.GrayScale
<編碼>方向</編碼<編碼>RenderingOptions.PaperOrientation</編碼
紙張大小RenderingOptions.PaperSize
Margins.TopRenderingOptions.MarginTop
邊界.底部RenderingOptions.MarginBottom
Margins.LeftRenderingOptions.MarginLeft
Margins.Right<編碼>RenderingOptions.MarginRight</編碼

物件設定屬性對應

物件設定屬性IronPdf 同等級產品
<編碼>Html內容</編碼RenderHtmlAsPdf() 的第一個參數
頁面 (URL)renderer.RenderUrlAsPdf(url)
HeaderSettings.Right = "[page]"TextHeader.RightText="{page}"

占位符語法差異

Header/footer 占位符在不同的程式庫中使用不同的語法:

Haukcode.DinkToPdfIronPDF
[page]{page}
[toPage]{總頁數}
[日期]<編碼>{日期}</編碼

線程安全與依賴注入

由於從 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()));
}
$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!
}
$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.dlllibwkhtmltox.solibwkhtmltox.dylib )。 這使得部署、CI/CD 管道和容器化變得複雜。 IronPdf 是獨立的,沒有外部二進位檔案。

執行緒安全限制:所需的SynchronizedConverter單例模式限制了架構靈活性,並且可能在負載下造成瓶頸。IronPDF在設計上是線程安全的,允許按要求實體。

現代網路標準: HTML5/CSS3 支援有限以及 JavaScript 執行不安全,限制了現代網頁內容的渲染能力。IronPDF的 Chromium 引擎提供當前的 Web 標準支援。

長期可行性:對已棄用技術的依賴會造成技術債務,並且隨著時間的推移而不斷累積。隨著專案在 2026 年前逐步擴展到 .NET 10 和 C# 14,繼續依賴不再維護的 wkhtmltopdf 封裝庫將變得越來越成問題。

優勢和考慮因素

Haukcode.DinkToPdf 的優勢

-免費開源:採用 MIT 許可證,無需支付任何許可費用 -基本功能:支援基本的 HTML 轉 PDF 轉換 -現有程式碼庫:對於已經使用 DinkToPdf 的團隊來說比較熟悉

Haukcode.DinkToPdf 注意事項

-嚴重安全漏洞: CVE-2022-35583 無法修復 -廢棄技術:基於已停止使用的 wkhtmltopdf 構建 -本地二進位依賴項:需要特定於平台的 DLL 文件 -螺紋安全問題:需要單例模式 -受限的 Web 標準:過時的 Qt WebKit 引擎 -不提供專業支援:僅提供社區援助 技術債:對廢棄項目的依賴加劇了風險

IronPDF的優勢

-主動安全性修補程式:定期更新以修復漏洞 -現代 Chromium 引擎:支援當前 Web 標準 -自包含:無原生二進位依賴項 -線程安全設計:靈活的部署模式 -全面支援 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,並探索全面的文件,以評估是否適合您的特定需求。