IRONSOFTWAREHOME
影片

如何在 C# 中渲染 Azure Blob 儲存中的圖像

Curtis Chau
Curtis Chau
Updated: 2026年7月19日

從PuppeteerSharp遷移到IronPDF可將您的PDF生成流程從具有300MB+ Chromium依賴的瀏覽器自動化工具轉換為具備自動記憶體管理的專用PDF庫。 本指南提供了一個逐步遷移路徑,消除了運行時Chromium下載,解決了載入時的記憶體增長問題,並增加了全面的PDF操作能力。

為什麼從PuppeteerSharp遷移到IronPDF

了解PuppeteerSharp

PuppeteerSharp 是Google的Puppeteer的.NET移植,為C#帶來了瀏覽器自動化功能。 它使用Chrome的內建列印至PDF功能生成PDF—相當於在瀏覽器中按Ctrl+P。 這會產生優化以紙張列印的輸出,與您在螢幕上看到的不同。

PuppeteerSharp為網頁測試和刮取而設計,並非為文件生成而設。 雖然有能力,但使用PuppeteerSharp生成PDF會帶來顯著的生產挑戰。

瀏覽器自動化問題

PuppeteerSharp是為瀏覽器自動化而設計,並不是為文件生成而設。 這對於使用它生成PDF時造成了根本性問題:

  1. 首次使用前需要下載300MB+的Chromium。 PuppeteerSharp的一個顯著缺點是其龐大的部署大小,主要是由於捆綁的Chromium二進制文件。 這一龐大大小會讓Docker映像膨脹並在無伺服器環境中導致冷啟動問題。

  2. 載入時報告的記憶體增長需要手動回收瀏覽器。 在持續負載下,PuppeteerSharp使用者報告了跨瀏覽器實例的記憶體累積,通常需要通過人工程式回收來解決。

  3. 復雜的異步模式與瀏覽器生命周期管理。

  4. 列印至PDF輸出(相當於Ctrl+P,而不是螢幕截圖)。 布局可能會重新流動,背景可能預設會被省略,輸出是為列印而分頁的,而不是匹配瀏覽器視圖的。

  5. 不支持PDF/A或PDF/UA以滿足合規要求。 PuppeteerSharp無法生成符合PDF/A(歸檔)或PDF/UA(可存取性)規範的文件。

  6. 無PDF操作 - 僅生成,無合併/拆分/編輯功能。 雖然PuppeteerSharp在生成PDF方面很高效,但它缺乏進一步操作的能力,如合併、拆分、保護或編輯PDF。

PuppeteerSharp vs IronPDF比較

方面PuppeteerSharpIronPDF
主要目的瀏覽器自動化PDF生成
Chromium依賴300MB+單獨下載內建優化引擎
API複雜性異步瀏覽器/頁面生命周期同步一行程式碼
初始化BrowserFetcher.DownloadAsync() + LaunchAsyncnew ChromePdfRenderer()
記憶體管理手動瀏覽器回收自動
載入時記憶體在高負載下報告增長在持續運行下穩定
PDF/A支持不可用支援
PDF/UA可存取性不可用支援
PDF編輯不可用合併、拆分、加蓋、編輯
數位簽名不可用支援
執行緒安全限制(根據上游指導)全面
授權MIT(開源)商業授權

平台支持

程式庫.NET Framework 4.7.2.NET Core 3.1.NET 6-8.NET 10
IronPDF全面全面全面全面
PuppeteerSharp透過netstandard2.0全面全面全面

IronPDF支持現代.NET目標,這意味著它可以無阻礙相容地進入大多數現有應用程式。


開始之前

前提條件

  1. .NET環境:.NET Framework 4.6.2+ 或.NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet存取: 有能力安裝NuGet套件
  3. IronPDF授權:ironpdf.com獲取您的授權金鑰

NuGet包變更

# Remove PuppeteerSharp
dotnet remove package PuppeteerSharp

# Remove downloaded Chromium binaries (~300MB recovered)
# Delete the .local-chromium folder

# Add IronPDF
dotnet add package IronPdf
SHELL

IronPDF無需BrowserFetcher.DownloadAsync() - 渲染引擎自動捆綁。

授權配置

// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

完整API參考

名稱空間變更

// Before: PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;

核心API對應

PuppeteerSharp APIIronPDFAPI注釋
new BrowserFetcher().DownloadAsync()不需要無瀏覽器下載
Puppeteer.LaunchAsync(options)不需要無瀏覽器管理
browser.NewPageAsync()不需要無頁面上下文
page.GoToAsync(url)renderer.RenderUrlAsPdf(url)直接渲染
page.SetContentAsync(html)renderer.RenderHtmlAsPdf(html)直接渲染
page.PdfAsync(path)pdf.SaveAs(path)渲染後
await page.CloseAsync()不需要自動清理
await browser.CloseAsync()不需要自動清理
PdfOptions.FormatRenderingOptions.PaperSize紙張大小
PdfOptions.LandscapeRenderingOptions.PaperOrientation方向
PdfOptions.MarginOptionsRenderingOptions.MarginTop/Bottom/Left/Right個別邊距
PdfOptions.PrintBackgroundRenderingOptions.PrintHtmlBackgrounds背景列印
PdfOptions.HeaderTemplateRenderingOptions.HtmlHeaderHTML標題
PdfOptions.FooterTemplateRenderingOptions.HtmlFooterHTML頁腳
page.WaitForSelectorAsync()RenderingOptions.WaitFor.HtmlElementId等待元素

程式碼遷移範例

範例1:基本HTML到PDF轉換

之前(PuppeteerSharp):

// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var browserFetcher = new BrowserFetcher();
        await browserFetcher.DownloadAsync();
        
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
        {
            Headless = true
        });
        
        await using var page = await browser.NewPageAsync();
        await page.SetContentAsync("<h1>Hello World</h1><p>This is a PDF document.</p>");
        await page.PdfAsync("output.pdf");
    }
}

之後(IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF document.</p>");
        pdf.SaveAs("output.pdf");
    }
}

此範例說明基本的架構差異。 PuppeteerSharp需要六個異步操作:BrowserFetcher.DownloadAsync()(300MB+ 的Chromium下載)、await using處置。

IronPDF消除了所有這些復雜性:建立一個SaveAs()。 無異步模式,無瀏覽器生命周期,無Chromium下載。 IronPDF的方法提供了更清晰的語法和與現代.NET應用程式的更好整合。 查看更多HTML到PDF文件以獲得完整的範例。

範例2:URL轉PDF轉換

之前(PuppeteerSharp):

// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var browserFetcher = new BrowserFetcher();
        await browserFetcher.DownloadAsync();
        
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
        {
            Headless = true
        });
        
        await using var page = await browser.NewPageAsync();
        await page.GoToAsync("https://www.example.com");
        await page.PdfAsync("webpage.pdf");
    }
}

之後(IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
    }
}

PuppeteerSharp使用PdfAsync()。 IronPDF提供了一個單一的RenderUrlAsPdf()方法,該方法在一次呼叫中處理導航和PDF生成。 在我們的教程中了解更多。

範例3:具有邊距的自定義頁面設置

之前(PuppeteerSharp):

// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var browserFetcher = new BrowserFetcher();
        await browserFetcher.DownloadAsync();
        
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
        {
            Headless = true
        });
        
        await using var page = await browser.NewPageAsync();
        await page.SetContentAsync("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
        
        await page.PdfAsync("custom.pdf", new PdfOptions
        {
            Format = PaperFormat.A4,
            Landscape = true,
            MarginOptions = new MarginOptions
            {
                Top = "20mm",
                Bottom = "20mm",
                Left = "20mm",
                Right = "20mm"
            }
        });
    }
}

之後(IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.MarginTop = 20;
        renderer.RenderingOptions.MarginBottom = 20;
        renderer.RenderingOptions.MarginLeft = 20;
        renderer.RenderingOptions.MarginRight = 20;
        
        var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
        pdf.SaveAs("custom.pdf");
    }
}

此範例展示了兩個程式庫之間的PDF選項映射。 PuppeteerSharp使用MarginOptions包含字串值 ("20mm")。 IronPDF使用RenderingOptions屬性,帶有直接紙張大小枚舉、方向枚舉和以毫米為單位的數值邊距值。

關鍵映射:

  • Format = PaperFormat.A4PaperSize = PdfPaperSize.A4
  • Landscape = truePaperOrientation = PdfPaperOrientation.Landscape
  • MarginOptions.Top = "20mm"MarginTop = 20 (數值毫米)

持續負載下的記憶體增長

使用者報告在持續負載下使用PuppeteerSharp發生記憶體累積,通常需要手動回收瀏覽器來緩解:

// PuppeteerSharp - memory growth typically requires periodic recycling
for (int i = 0; i < 1000; i++)
{
    var page = await browser.NewPageAsync();
    await page.SetContentAsync($"<h1>Document {i}</h1>");
    await page.PdfAsync($"doc_{i}.pdf");
    await page.CloseAsync();
}
// Recommended: await browser.CloseAsync(); and re-launch every N operations

//IronPDF- reuse a single renderer across operations
var renderer = new ChromePdfRenderer();
for (int i = 0; i < 1000; i++)
{
    var pdf = renderer.RenderHtmlAsPdf($"<h1>Document {i}</h1>");
    pdf.SaveAs($"doc_{i}.pdf");
    // Memory managed automatically
}
C#

IronPDF消除了PuppeteerSharp需要的瀏覽器池基礎設施:

// Before (PuppeteerSharp - delete entire class)
public class PuppeteerBrowserPool
{
    private readonly ConcurrentBag<IBrowser> _browsers;
    private readonly SemaphoreSlim _semaphore;
    private int _operationCount;
    // ... recycling logic ...
}

// After (IronPDF - simple reuse)
public class PdfService
{
    private readonly ChromePdfRenderer _renderer = new();

    public byte[] Generate(string html)
    {
        return _renderer.RenderHtmlAsPdf(html).BinaryData;
    }
}

關鍵遷移注意事項

異步到同步轉換

PuppeteerSharp需要全程使用async/await; IronPDF支持同步操作:

// PuppeteerSharp: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
    await new BrowserFetcher().DownloadAsync();
    await using var browser = await Puppeteer.LaunchAsync(...);
    await using var page = await browser.NewPageAsync();
    await page.SetContentAsync(html);
    return await page.PdfDataAsync();
}

// IronPDF: Sync default
public byte[] GeneratePdf(string html)
{
    var renderer = new ChromePdfRenderer();
    return renderer.RenderHtmlAsPdf(html).BinaryData;
}

// Or async when needed
public async Task<byte[]> GeneratePdfAsync(string html)
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}

邊距單位轉換

PuppeteerSharp使用字元單位; IronPDF使用數字毫米:

// PuppeteerSharp - string units
MarginOptions = new MarginOptions
{
    Top = "1in",      // 25.4mm
    Bottom = "0.75in", // 19mm
    Left = "1cm",     // 10mm
    Right = "20px"    // ~7.5mm at 96dpi
}

//IronPDF- numeric millimeters
renderer.RenderingOptions.MarginTop = 25;    // mm
renderer.RenderingOptions.MarginBottom = 19;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 8;
C#

標頭/頁腳佔位符轉換

PuppeteerSharp類IronPDF 佔位符
<span class='pageNumber'>{page}
<span class='totalPages'>{total-pages}
<span class='date'>{date}
<span class='title'>{html-title}

遷移後的新能力

遷移到IronPDF後,您將擁有PuppeteerSharp無法提供的功能:

PDF合併

var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");

水印

var watermark = new TextStamper
{
    Text = "CONFIDENTIAL",
    FontSize = 48,
    Opacity = 30,
    Rotation = -45
};
pdf.ApplyStamp(watermark);

密碼保護

pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;

數位簽名

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);

PDF/A合規性

pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);

性能比較摘要

指標PuppeteerSharpIronPDF改進
第一個PDF(冷啟動)45秒+約20秒快55%+
隨後的PDFs可變一致可預測
記憶體使用500MB+(增長)約50MB(穩定)減少90%的記憶體
磁碟空間(Chromium)300MB+0消除下載
瀏覽器下載必需的不需要零設定
執行緒安全有限全面可靠的並發性
PDF生成時間45秒20秒快55%

遷移檢查表

遷移前

  • 識別程式碼庫中的所有PuppeteerSharp用法
  • 文件邊距值(將字串轉換為毫米)
  • 注意標頭/頁腳佔位符語法轉換
  • 刪除瀏覽器池/回收基礎設施
  • 獲取IronPDF授權金鑰來自ironpdf.com

套件變更

  • 移除PuppeteerSharp NuGet包
  • 刪除.local-chromium資料夾以回收約300MB磁碟空間
  • 安裝IronPdf NuGet包:dotnet add package IronPdf

程式碼變更

  • 更新命名空間導入
  • 移除BrowserFetcher.DownloadAsync()調用
  • 移除Puppeteer.LaunchAsync()和瀏覽器管理
  • page.SetContentAsync() + RenderHtmlAsPdf()
  • page.GoToAsync() + RenderUrlAsPdf()
  • 將邊距字串轉換為毫米值
  • 轉換標頭/頁腳佔位符語法
  • 移除所有的瀏覽器/頁面釋放程式碼
  • 刪除瀏覽器池基礎設施
  • 在應用程式啟動時新增授權初始化

遷移後

  • PDF輸出的視覺比較
  • 載入測試以確保記憶體穩定性(應無需回收仍保持穩定)
  • 驗證標頭/頁腳渲染與頁碼的精確性
  • 根據需要新增新功能(安全性、水印、合併)

請注意: PuppeteerSharp是其各自所有者的註冊商標。 本網站不隸屬於、由其認可或贊助的PuppeteerSharp。所有產品名稱、標誌和品牌是其各自所有者的財產。 比較僅供參考,反映撰寫時公開可用的資訊。
Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

...
閱讀更多

相關文章

Key in blue circle

立即免費取得 30 天試用金鑰

Your trial license will be sent to your email address

無任何限制。100% 解鎖。無需信用卡。

bullet_checked無需信用卡或建立帳號無任何限制。100% 解鎖。無需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
預訂您的免費現場演示
Booking Badge

受到全球數百萬工程師的信任

Iron Software的客戶標誌
獲取您的無義務諮詢
填寫以下表格或電子郵件sales@ironsoftware.com
您的詳細資訊將始終保密
受到全球數百萬工程師的信任
Iron Software的客戶標誌
立即獲取您的30天試用金鑰
無需信用卡或帳戶建立