比較

2026 年最佳 C# 文件產生庫選擇

選擇 C# PDF 函式庫會影響專案的授權風險、部署靈活性和長期維護成本。大多數在評估階段看似合適的函式庫,在實際生產環境中都會暴露出一些缺陷——例如意想不到的 AGPL 許可要求、與瀏覽器不匹配的 HTML 渲染效果,或者僅在 Linux 系統上才會出現的記憶體洩漏問題。

本文透過程式碼範例對主要選項進行了比較,記錄了實踐中重要的權衡取捨,並包含並排程式碼比較,使用三個不同的程式庫產生相同的發票,以便您可以直接看到 API 的差異。

快速入門:三行程式碼即可將 HTML 轉換為 PDF

透過NuGet安裝:

Install-PackageIronPDF包

產生PDF文件:

using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");
$vbLabelText   $csharpLabel

無需額外配置,即可在 Windows、Linux、macOS 和 Docker 上運作。 由於IronPDF嵌入了相同的 Chromium 渲染引擎,因此輸出結果與 Chrome 一致。

評估標準

在比較不同圖書館之前,要先了解要評估哪些面向。 這些問題能及早發現生產問題:

標準測試什麼為什麼這很重要
HTML/CSS渲染將你的實際模板(使用 Flexbox/Grid)導入其中。大多數程式庫聲稱支援 HTML,但實際上最多只能渲染 CSS 2.1。
JavaScript執行使用 Chart.js 或動態表格內容進行測試不支援 JavaScript 的函式庫會產生空白部分。
許可模式請閱讀完整授權協議,而非摘要。AGPL 要求開源您的整個應用程式
平台支援部署到目標 Linux/Docker/ARM64 環境Windows 的成功並不能預測 Linux 的行為。
記憶體負載循環產生 100 多個文檔單一文檔測試會隱藏導致生產伺服器崩潰的漏洞
公佈價格請查看網站上是否標明價格。"接觸式銷售"通常指每年1.5萬美元至21萬美元的銷售額。

圖書館比較

IronPDF — 內建 Chromium,完全支援 CSS/JS

IronPDF將 Chromium 直接嵌入NuGet包中。 HTML渲染與Chrome一致,因為它使用的是Chrome的渲染引擎。 CSS Flexbox、Grid、自訂屬性和JavaScript都能如預期執行。

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;

var pdf = renderer.RenderHtmlAsPdf(@"
    <html>
    <head>
        <style>
            .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
            .card { background: linear-gradient(135deg, #f8fafc, #e2e8f0);
                    border-radius: 8px; padding: 20px; text-align: center; }
        </style>
    </head>
    <body>
        <div class='grid'>
            <div class='card'><h3>Revenue</h3><p>$1.2M</p></div>
            <div class='card'><h3>Users</h3><p>45,230</p></div>
            <div class='card'><h3>Uptime</h3><p>99.97%</p></div>
        </div>
    </body>
    </html>");
pdf.SaveAs("dashboard.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;

var pdf = renderer.RenderHtmlAsPdf(@"
    <html>
    <head>
        <style>
            .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
            .card { background: linear-gradient(135deg, #f8fafc, #e2e8f0);
                    border-radius: 8px; padding: 20px; text-align: center; }
        </style>
    </head>
    <body>
        <div class='grid'>
            <div class='card'><h3>Revenue</h3><p>$1.2M</p></div>
            <div class='card'><h3>Users</h3><p>45,230</p></div>
            <div class='card'><h3>Uptime</h3><p>99.97%</p></div>
        </div>
    </body>
    </html>");
pdf.SaveAs("dashboard.pdf");
$vbLabelText   $csharpLabel

需要考慮的權衡:嵌入式 Chromium 會使部署包增加約 200MB。 對於標準伺服器和容器部署,這是一次性下載,不會對執行時間產生影響。 對於像 Azure Functions 消費計畫這樣規模受限的環境,請檢查部署規模限制。 冷啟動時,首次產生 PDF 檔案需要 2-5 秒進行 Chromium 初始化; 後續幾代運行時間為 100-500 毫秒。 記憶體基線約為 150-200MB-據此規劃容器資源。

許可:永久許可起價 749 美元(1 位開發者)。 價格已在IronPDF上公佈。 不收取單件費用,不收取 AGPL 費用,無收入門檻。

iText 7 (iTextSharp) — AGPL 許可,有限 HTML

iText 是一個功能強大的 PDF 處理庫,擁有悠久的歷史。 pdfHTML 外掛程式提供 HTML 到 PDF 的轉換功能,但它不使用瀏覽器引擎——它使用自訂解析器來近似 CSS 2.1。

一家中型 SaaS 公司的生產團隊在將發票範本從Razor視圖遷移過來時發現了這個問題。 這些模板使用了 CSS Flexbox 來實現響應式列佈局。 整合 iText 的 pdfHTML 後,每張發票都以單列垂直堆疊的形式呈現。 gapjustify-content 屬性被靜默忽略。 開發團隊花了三週才意識到 pdfHTML 無法渲染他們現有的 CSS。

AGPL 的實際情況: iText 使用 AGPL 授權。 如果您的應用程式可透過網路存取(包括所有 Web 應用程式、API 和 SaaS 產品),則必須根據 AGPL 發布您的整個應用程式原始程式碼。 不僅僅是PDF模組。 一切。 iText及其母公司Apryse積極執行這項規定。

商業許可: iText 於 2024 年過渡到訂閱式授權。價格未公開-請聯絡銷售部門以取得報價。 第三方數據顯示,每年費用為 15,000 美元至 210,000 美元,視使用量而定。

PdfSharp — 採用 MIT 許可證,不含 HTML

PdfSharp是真正免費的,採用 MIT 許可證, NuGet下載量達 3490 萬次。 其缺點在於功能:它提供了一個基於座標的繪圖 API,但沒有 HTML 解析器、CSS 引擎和模板系統。

一個建立報告儀表板的團隊選擇了 PdfSharp,因為它免費且廣為人知。 他們花了四個月的時間編寫基於座標的佈局程式碼——計算每個文字元素的 X/Y 位置,逐像素繪製表格邊框,手動處理分頁符號。 當他們最終將自己的輸出與同一個 HTML 模板在瀏覽器中產生的輸出進行比較時,他們意識到他們建立的版本比基於 Chromium 的庫自動執行的操作還要糟糕。

PdfSharp 非常適合合併 PDF、添加浮水印以及從資料建立簡單的結構化文件。 如果不需要 HTML 渲染,這仍然是一個合理的選擇。

QuestPDF — 簡潔的 API,無需 HTML,收入門檻

QuestPDF提供流暢的 C# API,以程式設計方式建立文件。 API 設計確實非常出色——它是所有類別中最好的.NET庫 API 之一。

有兩個限制條件:QuestPDF 不會渲染 HTML(這是設計使然——這是一個刻意的架構選擇,而不是缺少的功能),而且社群授權適用於年總收入低於 100 萬美元的企業。 一旦貴公司達到該門檻,商業許可就成為強制性要求。 即將達到臨界點的公司應該在情況變得緊急之前為此過渡做好預算。

儘管 QuestPDF 明確反對 HTML,但開發人員在開始實施後經常會發現這一點,因為該庫會出現在"C# PDF 庫"的搜尋結果中,與支援 HTML 的庫並列出現。

wkhtmltopdf 封裝器 — 已棄用、未修補的 CVE

wkhtmltopdf 的時代已經過去了。 GitHub組織已於 2024 年 7 月存檔。 底層 QtWebKit 引擎已於 2015 年被 Qt 棄用。已知的 CVE(包括CVE-2022-35583 (CVSS 9.8,SSRF 漏洞可導致 AWS 憑證外洩))將永遠不會被修補。

像 DinkToPdf、NReco.PdfGenerator 和 WkHtmlToXSharp 這樣的 C# 封裝器都封裝了同一個已棄用的二進位檔案。 渲染引擎的功能大約停留在 Safari 2011 的水平:沒有 Flexbox,沒有 Grid, JavaScript有限。 對於新專案而言,這不是一個可行的選擇。

木偶師夏普 — 全面渲染,操作複雜

Puppeteer Sharp透過.NET綁定控制無頭 Chrome 瀏覽器。 渲染品質與 Chrome 一致,因為它就是Chrome。 這種權衡體現在操作層面:你需要管理外部瀏覽器進程,包括下載、池化、記憶體監控和崩潰復原。

using PuppeteerSharp;

// Downloads ~280MB Chromium on first run
await new BrowserFetcher().DownloadAsync();

await using var browser = await Puppeteer.LaunchAsync(
    new LaunchOptions { Headless = true });
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html);
return await page.PdfAsync(new PdfOptions { Format = PaperFormat.A4, PrintBackground = true });
using PuppeteerSharp;

// Downloads ~280MB Chromium on first run
await new BrowserFetcher().DownloadAsync();

await using var browser = await Puppeteer.LaunchAsync(
    new LaunchOptions { Headless = true });
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html);
return await page.PdfAsync(new PdfOptions { Format = PaperFormat.A4, PrintBackground = true });
$vbLabelText   $csharpLabel

在生產環境中,您還需要瀏覽器進程池、記憶體洩漏監控(Chromium 進程可能會發生記憶體洩漏)、崩潰復原和資源清理。 Docker 部署需要安裝 Chromium 依賴項-與標準的.NET映像相比,Dockerfile 的內容相當龐大。 如果你的團隊能夠承擔營運成本,那麼 木偶師夏普 是一個可行的選擇。

Aspose.PDF — 功能豐富,但有 Linux 記憶體問題

Aspose.PDF 提供全面的 PDF 功能和完善的文件。 主要問題是 Linux 穩定性:Aspose 依賴 System.Drawing.Common,而 System.Drawing.Common 在 Linux 上需要 libgdiplus——這是一個已停止維護且有記憶體洩漏問題的函式庫。 開發商報告涵蓋數年:

"在 Unix 環境下,數十個請求會導致服務記憶體耗盡,但在 Windows 環境下不會發生這種情況。" — Aspose 論壇,2022 年 3 月

對於僅限 Windows 系統的部署,Aspose 仍然能夠勝任。 對於跨平台或容器化部署,System.Drawing.Common 依賴項會帶來持續的風險。 商業許可費用起價約為每位開發者 999 美元。

功能對比

特徵IronPDFiText 7PdfSharpQuestPDFwkhtmltopdf木偶師Aspose
HTML 轉 PDF滿(鉻)有限(CSS 2.1)已棄用完整版(Chrome)有限的
CSS Flexbox/Grid是的是的
JavaScript是的有限的是的
Linux(無 libgdiplus)是的是的部分的*是的不適用是的
Docker部署標準.NET映像標準部分的*標準複雜的複雜的需要 libgdiplus
主動維護是的是的是的是的是的是的
公佈價格是的(749美元以上)否(年收入 1.5 萬美元至 21 萬美元)免費(MIT)是的(免費,低於100萬美元)自由的免費(MIT)是的(999美元以上)
永久許可是的無需訂閱不適用不適用不適用不適用是的
不包含AGPL協議是的否(需要商業用途)是的是的是的是的是的

*PdfSharp 記錄了某些配置下特定於平台的問題。

效能比較

在配置中等的雲端虛擬機器(4 個虛擬 CPU,8GB 記憶體)上使用包含 200 個元素的 HTML 發票範本進行測試,預熱後進行了 50 次迭代,取平均值:

設想IronPDF木偶師夏普iText pdfHTMLwkhtmltopdf
簡單的HTML頁面約150毫秒約500毫秒約200毫秒約200毫秒
複雜的CSS佈局(Flexbox/Grid)約250毫秒約600毫秒失敗/部分失敗約400毫秒(已損壞)
頁面大量使用了 JavaScript約350毫秒約800毫秒失敗失敗/部分失敗
每次操作內存約80MB約150MB約60MB約50MB
冷啟動(第一代)2-5秒3–8秒<1s<1s

iText 和 wkhtmltopdf 的冷啟動速度更快,因為它們不需要初始化瀏覽器引擎——但它們也無法渲染相同的內容。 效能比較僅在所有函式庫都能產生正確輸出的情況下才有意義。

程式碼比較:同一張發票,三個庫

當建構同一個文件時,這些庫之間的差異最為明顯。 以下是三種產生發票的方法。

IronPDF — HTML/CSS 方法

using IronPdf;

public class InvoiceGenerator
{
    public byte[] GenerateInvoice(InvoiceData data)
    {
        var renderer = new ChromePdfRenderer();

        string html = $@"
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body {{ font-family: 'Segoe UI', sans-serif; margin: 40px; }}
                h1 {{ color: #2c3e50; }}
                table {{ width: 100%; border-collapse: collapse; }}
                th {{ background: #3498db; color: white; padding: 12px; text-align: left; }}
                td {{ border-bottom: 1px solid #e0e0e0; padding: 10px; }}
                .total {{ font-weight: bold; font-size: 1.2em; text-align: right; margin-top: 20px; }}
            </style>
        </head>
        <body>
            <h1>Invoice #{data.InvoiceNumber}</h1>
            <table>
                <tr><th>Item</th><th>Qty</th><th>Price</th></tr>
                {string.Join("", data.Items.Select(i =>
                    $"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.Price:F2}</td></tr>"))}
            </table>
            <p class='total'>Total: ${data.Total:F2}</p>
        </body>
        </html>";

        var pdf = renderer.RenderHtmlAsPdf(html);
        return pdf.BinaryData;
    }
}
using IronPdf;

public class InvoiceGenerator
{
    public byte[] GenerateInvoice(InvoiceData data)
    {
        var renderer = new ChromePdfRenderer();

        string html = $@"
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body {{ font-family: 'Segoe UI', sans-serif; margin: 40px; }}
                h1 {{ color: #2c3e50; }}
                table {{ width: 100%; border-collapse: collapse; }}
                th {{ background: #3498db; color: white; padding: 12px; text-align: left; }}
                td {{ border-bottom: 1px solid #e0e0e0; padding: 10px; }}
                .total {{ font-weight: bold; font-size: 1.2em; text-align: right; margin-top: 20px; }}
            </style>
        </head>
        <body>
            <h1>Invoice #{data.InvoiceNumber}</h1>
            <table>
                <tr><th>Item</th><th>Qty</th><th>Price</th></tr>
                {string.Join("", data.Items.Select(i =>
                    $"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.Price:F2}</td></tr>"))}
            </table>
            <p class='total'>Total: ${data.Total:F2}</p>
        </body>
        </html>";

        var pdf = renderer.RenderHtmlAsPdf(html);
        return pdf.BinaryData;
    }
}
$vbLabelText   $csharpLabel

QuestPDF — 流暢的 API 方法

using QuestPDF.Fluent;
using QuestPDF.Infrastructure;

public class InvoiceGenerator
{
    public byte[] GenerateInvoice(InvoiceData data)
    {
        var document = Document.Create(container =>
        {
            container.Page(page =>
            {
                page.Size(PageSizes.A4);
                page.Margin(40);
                page.DefaultTextStyle(x => x.FontFamily("Segoe UI"));

                page.Header()
                    .Text($"Invoice #{data.InvoiceNumber}")
                    .FontSize(24).FontColor(Colors.Blue.Darken2);

                page.Content().Column(column =>
                {
                    column.Item().Table(table =>
                    {
                        table.ColumnsDefinition(cols =>
                        {
                            cols.RelativeColumn(3);
                            cols.RelativeColumn(1);
                            cols.RelativeColumn(1);
                        });

                        table.Header(header =>
                        {
                            header.Cell().Background(Colors.Blue.Medium).Padding(8)
                                .Text("Item").FontColor(Colors.White);
                            header.Cell().Background(Colors.Blue.Medium).Padding(8)
                                .Text("Qty").FontColor(Colors.White);
                            header.Cell().Background(Colors.Blue.Medium).Padding(8)
                                .Text("Price").FontColor(Colors.White);
                        });

                        foreach (var item in data.Items)
                        {
                            table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2)
                                .Padding(8).Text(item.Name);
                            table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2)
                                .Padding(8).Text(item.Quantity.ToString());
                            table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2)
                                .Padding(8).Text($"${item.Price:F2}");
                        }
                    });

                    column.Item().AlignRight().PaddingTop(20)
                        .Text($"Total: ${data.Total:F2}").FontSize(16).Bold();
                });
            });
        });

        using var stream = new MemoryStream();
        document.GeneratePdf(stream);
        return stream.ToArray();
    }
}
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;

public class InvoiceGenerator
{
    public byte[] GenerateInvoice(InvoiceData data)
    {
        var document = Document.Create(container =>
        {
            container.Page(page =>
            {
                page.Size(PageSizes.A4);
                page.Margin(40);
                page.DefaultTextStyle(x => x.FontFamily("Segoe UI"));

                page.Header()
                    .Text($"Invoice #{data.InvoiceNumber}")
                    .FontSize(24).FontColor(Colors.Blue.Darken2);

                page.Content().Column(column =>
                {
                    column.Item().Table(table =>
                    {
                        table.ColumnsDefinition(cols =>
                        {
                            cols.RelativeColumn(3);
                            cols.RelativeColumn(1);
                            cols.RelativeColumn(1);
                        });

                        table.Header(header =>
                        {
                            header.Cell().Background(Colors.Blue.Medium).Padding(8)
                                .Text("Item").FontColor(Colors.White);
                            header.Cell().Background(Colors.Blue.Medium).Padding(8)
                                .Text("Qty").FontColor(Colors.White);
                            header.Cell().Background(Colors.Blue.Medium).Padding(8)
                                .Text("Price").FontColor(Colors.White);
                        });

                        foreach (var item in data.Items)
                        {
                            table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2)
                                .Padding(8).Text(item.Name);
                            table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2)
                                .Padding(8).Text(item.Quantity.ToString());
                            table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2)
                                .Padding(8).Text($"${item.Price:F2}");
                        }
                    });

                    column.Item().AlignRight().PaddingTop(20)
                        .Text($"Total: ${data.Total:F2}").FontSize(16).Bold();
                });
            });
        });

        using var stream = new MemoryStream();
        document.GeneratePdf(stream);
        return stream.ToArray();
    }
}
$vbLabelText   $csharpLabel

PdfSharp — 座標繪圖方法

using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;

public class InvoiceGenerator
{
    public byte[] GenerateInvoice(InvoiceData data)
    {
        var document = new PdfDocument();
        var page = document.AddPage();
        var gfx = XGraphics.FromPdfPage(page);

        var titleFont = new XFont("Arial", 24);
        var headerFont = new XFont("Arial", 12, XFontStyleEx.Bold);
        var bodyFont = new XFont("Arial", 12);

        double y = 40;

        gfx.DrawString($"Invoice #{data.InvoiceNumber}", titleFont,
            XBrushes.DarkBlue, 40, y);
        y += 50;

        // Table header — manually positioned
        double[] colX = { 40, 300, 400 };
        double rowHeight = 30;

        gfx.DrawRectangle(XBrushes.SteelBlue, 40, y, 500, rowHeight);
        gfx.DrawString("Item", headerFont, XBrushes.White, colX[0] + 10, y + 20);
        gfx.DrawString("Qty", headerFont, XBrushes.White, colX[1] + 10, y + 20);
        gfx.DrawString("Price", headerFont, XBrushes.White, colX[2] + 10, y + 20);
        y += rowHeight;

        // Each row drawn individually with explicit coordinates
        foreach (var item in data.Items)
        {
            gfx.DrawRectangle(XPens.LightGray, 40, y, 500, rowHeight);
            gfx.DrawString(item.Name, bodyFont, XBrushes.Black, colX[0] + 10, y + 20);
            gfx.DrawString(item.Quantity.ToString(), bodyFont, XBrushes.Black, colX[1] + 10, y + 20);
            gfx.DrawString($"${item.Price:F2}", bodyFont, XBrushes.Black, colX[2] + 10, y + 20);
            y += rowHeight;
        }

        y += 20;
        gfx.DrawString($"Total: ${data.Total:F2}", headerFont, XBrushes.Black, 440, y);

        using var stream = new MemoryStream();
        document.Save(stream);
        return stream.ToArray();
    }
}
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;

public class InvoiceGenerator
{
    public byte[] GenerateInvoice(InvoiceData data)
    {
        var document = new PdfDocument();
        var page = document.AddPage();
        var gfx = XGraphics.FromPdfPage(page);

        var titleFont = new XFont("Arial", 24);
        var headerFont = new XFont("Arial", 12, XFontStyleEx.Bold);
        var bodyFont = new XFont("Arial", 12);

        double y = 40;

        gfx.DrawString($"Invoice #{data.InvoiceNumber}", titleFont,
            XBrushes.DarkBlue, 40, y);
        y += 50;

        // Table header — manually positioned
        double[] colX = { 40, 300, 400 };
        double rowHeight = 30;

        gfx.DrawRectangle(XBrushes.SteelBlue, 40, y, 500, rowHeight);
        gfx.DrawString("Item", headerFont, XBrushes.White, colX[0] + 10, y + 20);
        gfx.DrawString("Qty", headerFont, XBrushes.White, colX[1] + 10, y + 20);
        gfx.DrawString("Price", headerFont, XBrushes.White, colX[2] + 10, y + 20);
        y += rowHeight;

        // Each row drawn individually with explicit coordinates
        foreach (var item in data.Items)
        {
            gfx.DrawRectangle(XPens.LightGray, 40, y, 500, rowHeight);
            gfx.DrawString(item.Name, bodyFont, XBrushes.Black, colX[0] + 10, y + 20);
            gfx.DrawString(item.Quantity.ToString(), bodyFont, XBrushes.Black, colX[1] + 10, y + 20);
            gfx.DrawString($"${item.Price:F2}", bodyFont, XBrushes.Black, colX[2] + 10, y + 20);
            y += rowHeight;
        }

        y += 20;
        gfx.DrawString($"Total: ${data.Total:F2}", headerFont, XBrushes.Black, 440, y);

        using var stream = new MemoryStream();
        document.Save(stream);
        return stream.ToArray();
    }
}
$vbLabelText   $csharpLabel

IronPDF版本使用 HTML/CSS-這是大多數開發人員已經掌握的技能。 QuestPDF 版本需要學習特定領域的 Fluent API,但它提供了結構。 PdfSharp 版本需要手動計算每個像素位置-每一列偏移、每一行高度、每一道邊框都是單獨繪製的。

我該選擇哪家圖書館?

當我評估這些函式庫時,決策過程非常簡單明了:

需要使用現代 CSS 將 HTML 轉換為 PDF 嗎? IronPDF或 木偶師夏普 是比較實用的選擇。 IronPDF內部支援 Chromium; 木偶師夏普 需要您管理外部瀏覽器進程。 wkhtmltopdf 不適用於新專案。 iText 的 pdfHTML 無法渲染 Flexbox 或 Grid。

想透過程式設計方式從資料建立文檔,而無需 HTML? QuestPDF 的流暢 API 高效且設計精良。 PdfSharp 提供更低層級的控制,但要實現相同的佈局,需要編寫更多的程式碼。

跨平台部署(Linux、Docker、雲端)? IronPDF、QuestPDF 和 木偶師夏普 無需 libgdiplus 依賴即可在 Linux 上運行。 Aspose.PDF 已記錄到在 Linux 系統上有記憶體洩漏問題。 PdfSharp 平台支援不完整,有已知問題。

許可限制? PdfSharp (MIT) 和 木偶師夏普 (MIT) 是免費的,沒有任何附加條件。 QuestPDF 在年收入低於 100 萬美元時是免費的。 iText 需要遵守 AGPL 協議或獲得商業許可(每年 1.5 萬美元至 21 萬美元)。 IronPDF 的永久許可證起價為 749 美元。 Aspose 的起價約為 999 美元。

在你做出決定之前

使用實際內容進行測試,而不是"Hello World"程式。儘早部署到目標平台。 測試記憶體佔用時,要測試 100 個以上的文檔,而不是單一文檔。 請與您的法律團隊一起閱讀完整的許可協議文本。 如果您的目標是無伺服器架構,請檢查冷啟動延遲。

IronPDF提供功能齊全的試用版,可供您根據自身需求進行評估。