比較

C# 中免費 PDF 庫的隱藏成本

當開發者搜尋"免費 C# PDF 庫"時,會發現數十個 NuGet 包,它們似乎可以免費解決開發者的問題。但實際上,.NET PDF 領域中所有"免費"選項都存在一些限制,這些限制會在開發開始後逐漸顯現——例如 AGPL 原始碼公開、缺少 HTML 支援、依賴項存在未修復的 CVE 漏洞,或者達到收入門檻後必須獲得許可。 本文以具體證據記錄了這些限制,以便您在做出決定之前評估實際成本。

在 .NET PDF 生態系統中,"免費"的真正意義是什麼?

在這個領域,"免費"一詞對應著五種不同的授權模式,混淆這些模式會造成真正的法律和技術風險:

MIT/Apache(真正寬鬆): PdfSharp使用 MIT 許可證。 沒有收入限制,沒有版權保護,沒有資訊揭露要求。 您可以將其作為商業軟體無條件發布。 權衡的關鍵在於能力,而不是許可。

AGPL(具有約束力的開源軟體): iTextSharp(iText Core)使用 AGPL 協定。 如果您的應用程式可透過網路存取(包括所有 Web 應用程式、API 和 SaaS 產品),則必須根據 AGPL 發布您的整個應用程式原始程式碼。 不僅僅是PDF生成代碼。 您的專有業務邏輯、您的身分驗證系統,所有的一切。

收入限制型社群授權:QuestPDF的社群授權涵蓋年總收入低於 100 萬美元的企業。 一旦超過該門檻,無論您實際使用QuestPDF的頻率如何,都必須獲得商業許可。

已棄用且無人維護:wkhtmltopdf及其 .NET 封裝程式(DinkToPdf、NReco.PdfGenerator)已停止開發。 GitHub 組織已於 2024 年 7 月歸檔。已知的 CVE 漏洞將永遠不會被修復。

免費但運行成本高昂: Puppeteer Sharp 和 Playwright 採用 MIT 許可證,但它們需要管理外部瀏覽器進程——下載、進程池、記憶體洩漏監控、崩潰恢復。 基礎設施成本可能超過商業許可證費用。

iTextSharp和 AGPL 陷阱

iTextSharp 是 NuGet 上下載量最高的 PDF 軟體包之一,下載量約 3,000 萬次。 許多開發者安裝它時都以為它可以免費用於商業用途。 並非如此。

許可的現實

2009 年,iText 從 LGPL 切換到 AGPL。 根據 AGPL 協議,在任何可透過網路存取的應用程式中部署 iText 都需要您根據 AGPL 條款發布您的整個應用程式的原始程式碼。 iText 自己的文件中明確指出:"未經 AGPL 許可,不得在網路上部署 iText,除非公開您自己的應用程式的完整原始程式碼。"

這並非理論上的。 它適用於您的 Web 應用程式、透過網路公開的內部工具、SaaS 產品和客戶專案。

積極執法

iText及其母公司Apryse積極尋求許可證合規性。 Beeman & Muchmore 律師事務所 2025 年 9 月的分析報告記錄了該公司的執法模式,指出該公司"在 2023 年 2 月品牌重塑前後,在其許可合規部門進行了大規模招聘"。該律師事務所將這些做法描述為類似於專利流氓行為——公司"收購專利組合,並隨意主張這些專利,以換取辯護費用/騷擾和解金"。

iText 本身也承認了這種立場,並表示很少需要採取法律行動,因為"相關人員明白,被起訴對他們沒有好處"。

舊版漏洞失效

一些開發者嘗試使用根據 LGPL 發布的iTextSharp4.1.6。 iText 的常見問題明確指出:這些版本已停止維護,沒有安全性補丁,而且 API 早於現代 PDF 要求。

商業許可證費用是多少?

對於無法遵守 AGPL 協議的公司,iText 提供商業許可。 截至 2024 年, iText 已從永久授權模式過渡到訂閱授權模式。 價格不公開-請聯絡銷售部門以取得報價。 供應商提供的第三方數據顯示,根據使用量的不同,每年的成本在 15,000 美元到 210,000 美元之間。

相比之下,IronPDF 的永久授權起價為 749 美元,價格已在網站上公佈,並且無需每年訂閱即可繼續使用。

iText 的 HTML 渲染實際產生什麼

pdfHTML 外掛程式不使用瀏覽器引擎。以下是嘗試使用現代 CSS 時發生的情況:

using iText.Html2pdf;
using iText.Kernel.Pdf;

// This HTML uses CSS Flexbox — a standard layout technique since 2015
string html = @"
<html><head><style>
    .container { display: flex; gap: 20px; justify-content: space-between; }
    .card { flex: 1; padding: 15px; border: 1px solid #ccc; border-radius: 8px; }
</style></head>
<body>
    <div class='container'>
        <div class='card'>Revenue: $1.2M</div>
        <div class='card'>Expenses: $890K</div>
        <div class='card'>Profit: $310K</div>
    </div>
</body></html>";

using var writer = new PdfWriter("itext-output.pdf");
using var pdf = new PdfDocument(writer);
// Result: three cards stacked vertically, no flex layout applied
// The gap, border-radius, and justify-content are ignored
HtmlConverter.ConvertToPdf(html, pdf, new ConverterProperties());
using iText.Html2pdf;
using iText.Kernel.Pdf;

// This HTML uses CSS Flexbox — a standard layout technique since 2015
string html = @"
<html><head><style>
    .container { display: flex; gap: 20px; justify-content: space-between; }
    .card { flex: 1; padding: 15px; border: 1px solid #ccc; border-radius: 8px; }
</style></head>
<body>
    <div class='container'>
        <div class='card'>Revenue: $1.2M</div>
        <div class='card'>Expenses: $890K</div>
        <div class='card'>Profit: $310K</div>
    </div>
</body></html>";

using var writer = new PdfWriter("itext-output.pdf");
using var pdf = new PdfDocument(writer);
// Result: three cards stacked vertically, no flex layout applied
// The gap, border-radius, and justify-content are ignored
HtmlConverter.ConvertToPdf(html, pdf, new ConverterProperties());
Imports iText.Html2pdf
Imports iText.Kernel.Pdf

' This HTML uses CSS Flexbox — a standard layout technique since 2015
Dim html As String = "
<html><head><style>
    .container { display: flex; gap: 20px; justify-content: space-between; }
    .card { flex: 1; padding: 15px; border: 1px solid #ccc; border-radius: 8px; }
</style></head>
<body>
    <div class='container'>
        <div class='card'>Revenue: $1.2M</div>
        <div class='card'>Expenses: $890K</div>
        <div class='card'>Profit: $310K</div>
    </div>
</body></html>"

Using writer As New PdfWriter("itext-output.pdf")
    Using pdf As New PdfDocument(writer)
        ' Result: three cards stacked vertically, no flex layout applied
        ' The gap, border-radius, and justify-content are ignored
        HtmlConverter.ConvertToPdf(html, pdf, New ConverterProperties())
    End Using
End Using
$vbLabelText   $csharpLabel

輸出結果是將卡片垂直堆疊,沒有彈性佈局。 gapborder-radiusjustify-content屬性將被忽略。 這是 iText 的 HTML 渲染狀態——它近似於 CSS 2.1,但不執行 Flexbox、Grid 或 JavaScript。

IronPDF之所以能正確渲染,是因為它使用了嵌入式Chromium——與Chrome相同的引擎。 輸出結果與瀏覽器中顯示的內容一致:

using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html); // Same HTML as above
pdf.SaveAs("ironpdf-output.pdf");
// Result: three cards in a horizontal row with proper spacing and rounded corners
using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html); // Same HTML as above
pdf.SaveAs("ironpdf-output.pdf");
// Result: three cards in a horizontal row with proper spacing and rounded corners
Imports IronPdf

Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html) ' Same HTML as above
pdf.SaveAs("ironpdf-output.pdf")
' Result: three cards in a horizontal row with proper spacing and rounded corners
$vbLabelText   $csharpLabel

PdfSharp:真正免費,真正有限。

PdfSharp採用 MIT 許可證,沒有任何限制。 NuGet 下載量超過 3,490 萬次。 商業用途可免費使用,沒有任何附加條件。 權衡之下,關鍵在於它能做什麼。

完全不渲染 HTML

PdfSharp提供繪圖 API。 您可以使用明確座標呼叫DrawString()DrawRectangle()DrawImage() 。 沒有HTML解析器,沒有CSS引擎,也沒有模板系統。 如果您的應用程式從 HTML 範本產生 PDF(例如從 Razor 視圖產生發票、從儀表板 HTML 產生報告、將電子郵件歸檔),則PdfSharp無法做到這一點。

常用的解決方法HtmlRenderer.PdfSharp僅支援 HTML 4.01 和 CSS Level 2。 不使用 Flexbox。 無網格。 禁用 JavaScript。 不支援網頁字體。 如果你的 HTML 程式碼使用了過去十年中的任何 CSS 特性,它將無法渲染。

PdfSharp 的適用場景

PdfSharp非常適合從資料產生結構化文件——帶有程序化佈局的發票、簡單的報告、PDF 合併和分割、浮水印和註釋。 如果你不需要 HTML 渲染,而且目標平台是 Windows,那麼它仍然是一個合理的選擇。

QuestPDF:免費使用,直到您的公司成長

QuestPDF提供了一個優雅流暢的 C# API,以程式設計方式建立文件。 API設計確實不錯。 這種授權模式造成了巨大的鴻溝。

營收門檻

QuestPDF 的社群授權涵蓋個人、年總收入低於 100 萬美元的企業、非營利組織和開源專案。 一旦公司收入超過 100 萬美元,無論您使用QuestPDF的程度如何,都必須購買商業許可證。

以下是成長場景的範例:一家年收入 90 萬美元的新創公司免費使用 QuestPDF。 金額達到 1,000,001 美元,他們需要商業許可證。 如果他們沒有為此做好預算,那麼他們就必須在支付許可費和在時間壓力下遷移到另一個庫之間做出選擇。 兩個選項都不是免費的。

接近門檻的公司需要在規劃中考慮這一點。 如果你閱讀許可條款,你不會感到驚訝,但許多團隊是在將庫嵌入到他們的程式碼庫之後才發現這一點。

不支援 HTML — 有意為之

QuestPDF 不渲染 HTML。 這是有意為之的設計選擇,並非功能缺失。 該庫的定位是"停止與 HTML 到 PDF 的轉換作鬥爭"——它用程式化的 C# 程式碼取代了 HTML 方法。

儘管定位很明確,但開發人員經常認為QuestPDF可以處理 HTML,因為它出現在"C# PDF 庫"的搜尋結果中,與支援 HTML 的庫並列出現。 2022 年至 2024 年的 GitHub 討論顯示,開發人員在開始實施後才發現這項限制。 維護人員始終確認暫無計劃支援 HTML。

wkhtmltopdf封裝器:已棄用且存在未修補的 CVE

wkhtmltopdf 是一個流行的 HTML 轉 PDF 命令列工具。 目前有幾個 C# 封裝庫:DinkToPdf、NReco.PdfGenerator 和 WkHtmlToXSharp。它們都封裝了同一個已棄用的二進位檔案。

狀態

GitHub 組織已於 2024 年 7 月 10 日存檔wkhtmltopdf 狀態頁面將該項目標記為已棄用。 Homebrew 於 2024 年 12 月 16 日禁用了酒桶。 底層 QtWebKit 引擎已於 2015 年被 Qt 棄用,並於 2016 年移除。

關鍵漏洞—永遠無法修復

CVE-2022-35583 (CVSS 9.8 嚴重):伺服器端請求偽造。 攻擊者將 iframe 標籤注入wkhtmltopdf處理的 HTML 內容中。 該 iframe 指向http://169.254.169.254/latest/meta-data/ — AWS EC2 元資料端點。 產生的 PDF 檔案包含回應,其中包括 IAM 憑證。


<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"
        style="width:100%;height:500px;"></iframe>

<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"
        style="width:100%;height:500px;"></iframe>
HTML

CVE-2020-21365 (CVSS 7.5 高風險):目錄遍歷漏洞允許遠端攻擊者透過精心建構的 HTML 讀取本機檔案。

這些漏洞已被記錄在案,可以公開利用,而且永遠不會被修復。 在生產環境中執行 wkhtmltopdf(尤其是處理使用者提交的 HTML)會創建特定的、可利用的攻擊面。

渲染品質

除了安全性之外,wkhtmltopdf 的 QtWebKit 引擎的功能大約只相當於 Safari 2011。 不支援 CSS Flexbox,不支援 CSS Grid,CSS3 支援有限,JavaScript 執行不穩定。 在任何現代瀏覽器中都能正確顯示的內容,透過wkhtmltopdf渲染後都會出現錯誤。

"免費"的真正代價

開發人員的時間是最大的成本。

由於PdfSharp缺乏 HTML 支持,一個團隊不得不使用基於座標的繪圖命令手動定位每個元素,而這些佈局原本可以用 20 行 HTML/CSS 程式碼表達,這浪費了開發人員的時間,造成了可衡量的成本。

保守估計:每月花費 2 個開發人員工作日來維護變通方案和手動佈局,每小時費用為 150 美元,每年成本為 28,800 美元。 IronPDF的企業版授權價格更低。 免費庫對開發者生產力的降低成本高於商業替代方案的授權成本。

這並非PdfSharp獨有的問題。 管理 Puppeteer Sharp 瀏覽器進程的團隊——編寫池邏輯、監控記憶體洩漏、處理崩潰恢復——在工程時間上的花費,相當於他們在許可費上節省的費用。

技術債不斷累積

Quandary Peak Research 在 2025 年 12 月的一份分析報告中直言不諱地指出:"開源軟體的'免費'標籤名不副實,掩蓋了巨大的隱性成本和潛在的責任。"

任何針對缺失功能的變通方案都會增加需要維護、測試和遷移的程式碼,而當需求改變時,這些程式碼又需要進行遷移。 2022 年 CISQ 報告發現,美國累計軟體技術債達 1.52 兆美元。 每次團隊編寫基於座標的佈局程式碼而不是使用 HTML 範本時,PDF 庫的變通方法都會增加這個數字。

安全風險會造成經濟損失。

產業數據顯示,82% 的開源元件已過時,75% 的程式碼庫包含漏洞,49% 的程式碼庫包含高風險漏洞。 PDF 庫存在較高的風險,因為它們處理使用者提供的內容並以伺服器權限運行。

Equifax 資料外洩事件——1.47 億筆記錄外洩——是由於開源元件中未修補的漏洞造成的。 經濟損失超過14億美元。 攻擊向量屬於同一類漏洞(透過未維護的庫處理不受信任的輸入),與wkhtmltopdf的 CVE 代表的漏洞相同。

遷移的成本比一開始就做好要高得多。

從有限的免費庫開始,以後再進行遷移,比一開始就選擇一個合適的庫成本更高。 遷移涉及學習新的 API、重寫 PDF 生成程式碼、以不同格式重新建立範本、對每種文件類型進行回歸測試以及驗證下游系統的輸出。 第一年預算中沒有用於 PDF 工具的團隊,通常會在第二年花費 5 萬美元以上用於遷移。

IronPDF如何解決這些局限性

當我在設計 IronPDF 的架構時,決定嵌入 Chromium 並不是因為擁有最新的技術,而是因為要給開發者提供與他們在瀏覽器中看到的結果一致的結果。 CSS Flexbox 有效。 CSS Grid 有效。 JavaScript 程式碼執行。 網頁字體渲染。 你寫 HTML 和 CSS,PDF 輸出結果與 Chrome 瀏覽器一致。

using IronPdf;

var renderer = new ChromePdfRenderer();

var pdf = renderer.RenderHtmlAsPdf(@"
    <html>
    <head>
        <style>
            .dashboard { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
            .metric { padding: 20px; background: #f8f9fa; border-radius: 8px; text-align: center; }
            .metric h3 { margin: 0; color: #6c757d; font-size: 0.85rem; }
            .metric .value { font-size: 2rem; font-weight: bold; color: #212529; }
        </style>
    </head>
    <body>
        <div class='dashboard'>
            <div class='metric'><h3>Revenue</h3><div class='value'>$1.2M</div></div>
            <div class='metric'><h3>Users</h3><div class='value'>45,230</div></div>
            <div class='metric'><h3>Uptime</h3><div class='value'>99.97%</div></div>
        </div>
    </body>
    </html>");

pdf.SaveAs("dashboard.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();

var pdf = renderer.RenderHtmlAsPdf(@"
    <html>
    <head>
        <style>
            .dashboard { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
            .metric { padding: 20px; background: #f8f9fa; border-radius: 8px; text-align: center; }
            .metric h3 { margin: 0; color: #6c757d; font-size: 0.85rem; }
            .metric .value { font-size: 2rem; font-weight: bold; color: #212529; }
        </style>
    </head>
    <body>
        <div class='dashboard'>
            <div class='metric'><h3>Revenue</h3><div class='value'>$1.2M</div></div>
            <div class='metric'><h3>Users</h3><div class='value'>45,230</div></div>
            <div class='metric'><h3>Uptime</h3><div class='value'>99.97%</div></div>
        </div>
    </body>
    </html>");

pdf.SaveAs("dashboard.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()

Dim pdf = renderer.RenderHtmlAsPdf("
    <html>
    <head>
        <style>
            .dashboard { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
            .metric { padding: 20px; background: #f8f9fa; border-radius: 8px; text-align: center; }
            .metric h3 { margin: 0; color: #6c757d; font-size: 0.85rem; }
            .metric .value { font-size: 2rem; font-weight: bold; color: #212529; }
        </style>
    </head>
    <body>
        <div class='dashboard'>
            <div class='metric'><h3>Revenue</h3><div class='value'>$1.2M</div></div>
            <div class='metric'><h3>Users</h3><div class='value'>45,230</div></div>
            <div class='metric'><h3>Uptime</h3><div class='value'>99.97%</div></div>
        </div>
    </body>
    </html>")

pdf.SaveAs("dashboard.pdf")
$vbLabelText   $csharpLabel

它使用了 CSS Grid、 border-radius 、自訂字體大小和語義化 HTML。 PdfSharp無法解析它。QuestPDF無法解析它。 iText 的 pdfHTML 將其渲染為垂直堆疊。wkhtmltopdf完全忽略網格。 IronPDF 產生與瀏覽器相符的三列儀表板。

許可流程無意外

IronPDF採用永久許可模式-一次購買,無限期使用。 不公開AGPL原始碼。 沒有收入門檻。 無需強制訂閱。 單一開發人員的定價從 749 美元起,並在網站上公佈,而不是在"聯絡銷售"頁面後面。

無需變通方法即可跨平台

IronPDF 可在 Windows、Linux、macOS 和 Docker 容器上執行,無需libgdiplus依賴項、System.Drawing.Common 問題或本機二進位安裝。 Docker 部署是一個標準的 .NET 基礎映像,無需任何額外配置。

做出決定。

要求PdfSharpQuestPDFiTextSharpwkhtmltopdfIronPDF
真正自由(MIT/許可)收入低於100萬美元否(AGPL)
HTML 至 PDF限額已棄用
現代 CSS(Flexbox/Grid)
JavaScript 執行限額
主動安全維護
出版價格不適用不適用
無收入門檻不適用

對於只需要根據資料以程式設計方式建立 PDF 的應用程式(不需要 HTML 模板,也不需要 Web 內容), PdfSharp或QuestPDF可能就足夠了,具體取決於公司規模。

對於使用現代 CSS 將 HTML 轉換為 PDF 的應用程序,選擇範圍縮小到以下幾種:支付 iText 的商業許可費(每年 15,000 美元至 210,000 美元)、管理 Puppeteer 的瀏覽器基礎架構,或使用專為此任務設計的商業庫。 IronPDF 的永久許可證售價 749 美元,是實現生產級 HTML 渲染的最經濟途徑。

"免費 PDF 庫 C#"這個短語會吸引開發者採用一些會在後續環節造成更大成本的解決方案。 評估時應基於總體擁有成本(許可費、開發人員時間、安全維護和遷移風險),而不是初始價格。