跳過到頁腳內容
遷移指南

如何用 C# 從 PuppeteerSharp 轉移到 IronPDF

從PuppeteerSharp轉換到IronPDF可將您的 PDF 生成工作流程從依賴 300MB 以上的瀏覽器自動化工具轉換為具有自動記憶體管理功能的專用 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.複雜的 async 模式與瀏覽器生命週期管理。

4.Print-to-PDF 輸出(等同於 Ctrl+P,而非螢幕擷取)。 版面可能會回流,背景可能會依預設省略,而且輸出會以分頁方式列印,而非配合瀏覽器的視埠。

5.不支援 PDF/A 或 PDF/UA,以符合法規要求。PuppeteerSharp無法製作 PDF/A (歸檔) 或 PDF/UA (無障礙) 相容的文件。

6.無 PDF 操作 - 僅生成,無合併/分割/編輯。 雖然PuppeteerSharp能有效率地產生 PDF,但它缺乏進一步操作的功能,例如合併、分割、保護或編輯 PDF。

PuppeteerSharp與IronPDF的比較

範疇 PuppeteerSharp IronPDF
主要目的 瀏覽器自動化 生成 PDF
Chromium相依性 300MB+ 獨立下載 內建最佳化引擎
API複雜性 同步瀏覽器/網頁生命週期 同步單行字
初始化 BrowserFetcher.DownloadAsync() + LaunchAsync new ChromePdfRenderer()
記憶體管理 需要手動回收瀏覽器 自動化
負載下的記憶體 500MB+ 有洩漏 ~50MB 穩定
冷啟動 45 秒以上 ~20 秒
PDF/A支援 無法提供 支援
PDF/UA 可訪問性 無法提供 支援
PDF編輯 無法提供 合併、分割、蓋章、編輯
數位簽名 無法提供 支援
線程安全 限額 全文
專業支援 社區 有 SLA 的商業翻譯

平台支援

| 圖書館 |.NET Framework 4.7.2|.NET Core 3.1|.NET 6-8|.NET 10| | --------- | :---: | :---: | :---: | :---: ||IronPDF| 全文 | 全文 | 全文 | 全文 ||PuppeteerSharp| 限額 | 全文 | 全文 | 待辦的 | IronPDF 跨 .NET 平台的廣泛支援,可確保開發人員在各種環境中利用IronPDF而不會遇到相容性問題,為 2025 年和 2026 年的現代 .NET 應用程式提供靈活的選擇。


開始之前

先決條件

  1. .NET環境: .NET Framework 4.6.2+ 或.NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet存取權限:能夠安裝NuGet套件
  3. IronPDF許可證:請從IronPDF取得您的許可證密鑰。

NuGet 套件變更

# Remove PuppeteerSharp
dotnet remove package PuppeteerSharp

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

# Add IronPDF
dotnet add package IronPdf
# 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";
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

完整的 API 參考資料

命名空間變更

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

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
' Before: PuppeteerSharp
Imports PuppeteerSharp
Imports PuppeteerSharp.Media
Imports System.Threading.Tasks

' After: IronPDF
Imports IronPdf
Imports IronPdf.Rendering
$vbLabelText   $csharpLabel

核心 API 對應

PuppeteerSharp API IronPDF API 筆記
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.Format RenderingOptions.PaperSize 紙張大小
PdfOptions.Landscape RenderingOptions.PaperOrientation 導向
PdfOptions.MarginOptions RenderingOptions.MarginTop/Bottom/Left/Right 個別邊距
PdfOptions.PrintBackground RenderingOptions.PrintHtmlBackgrounds 背景印刷
PdfOptions.HeaderTemplate RenderingOptions.HtmlHeader HTML 標頭
PdfOptions.FooterTemplate RenderingOptions.HtmlFooter HTML 頁腳
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");
    }
}
// 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");
    }
}
Imports PuppeteerSharp
Imports System.Threading.Tasks

Module Program
    Async Function Main(args As String()) As Task
        Dim browserFetcher = New BrowserFetcher()
        Await browserFetcher.DownloadAsync()

        Using browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
            .Headless = True
        })

            Using page = Await browser.NewPageAsync()
                Await page.SetContentAsync("<h1>Hello World</h1><p>This is a PDF document.</p>")
                Await page.PdfAsync("output.pdf")
            End Using
        End Using
    End Function
End Module
$vbLabelText   $csharpLabel

After (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");
    }
}
// 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");
    }
}
Imports IronPdf

Class Program
    Shared Sub Main(args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF document.</p>")
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

本範例展示了基本的架構差異。PuppeteerSharp需要六個非同步操作:BrowserFetcher.DownloadAsync()(300MB+ Chromium 下載),Puppeteer.LaunchAsync()browser.NewPageAsync()page.SetContentAsync(),@@--CODE-19528--@@ 以及 @@--CODE-19529--@@ 進行適當的處置。

IronPDF 消除了所有這些複雜性:建立一個 ChromePdfRenderer,呼叫 RenderHtmlAsPdf(),以及 SaveAs()。 沒有 async 模式、沒有瀏覽器生命週期、沒有 Chromium 下載。IronPDF的方法提供了更簡潔的語法,並能更好地與現代 .NET 應用程式整合。 請參閱 HTML to 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");
    }
}
// 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");
    }
}
Imports PuppeteerSharp
Imports System.Threading.Tasks

Module Program
    Async Function Main(args As String()) As Task
        Dim browserFetcher = New BrowserFetcher()
        Await browserFetcher.DownloadAsync()

        Using browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
            .Headless = True
        })

            Using page = Await browser.NewPageAsync()
                Await page.GoToAsync("https://www.example.com")
                Await page.PdfAsync("webpage.pdf")
            End Using
        End Using
    End Function
End Module
$vbLabelText   $csharpLabel

After (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");
    }
}
// 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");
    }
}
Imports IronPdf

Class Program
    Shared Sub Main(ByVal args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
        pdf.SaveAs("webpage.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

PuppeteerSharp 使用 GoToAsync() 導覽至 URL,然後使用 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"
            }
        });
    }
}
// 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"
            }
        });
    }
}
Imports PuppeteerSharp
Imports PuppeteerSharp.Media
Imports System.Threading.Tasks

Module Program
    Async Function Main(args As String()) As Task
        Dim browserFetcher = New BrowserFetcher()
        Await browserFetcher.DownloadAsync()

        Await Using browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
            .Headless = True
        })

            Await Using 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 With {
                    .Format = PaperFormat.A4,
                    .Landscape = True,
                    .MarginOptions = New MarginOptions With {
                        .Top = "20mm",
                        .Bottom = "20mm",
                        .Left = "20mm",
                        .Right = "20mm"
                    }
                })
            End Using
        End Using
    End Function
End Module
$vbLabelText   $csharpLabel

After (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");
    }
}
// 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");
    }
}
Imports IronPdf
Imports IronPdf.Rendering

Class Program
    Shared Sub Main(args As String())
        Dim 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

        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>")
        pdf.SaveAs("custom.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

此範例顯示 PDF 選項如何在兩個函式庫之間對應。PuppeteerSharp使用 PdfOptions,其中 FormatLandscapeMarginOptions 包含字串值 ("20mm")。IronPDF使用 RenderingOptions 屬性,其中包含直接的紙張尺寸枚舉、方向枚舉和以毫米為單位的數值邊距值。

關鍵對應:

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

記憶體洩漏問題

PuppeteerSharp 在持續負載下會造成記憶體累積:

// ❌PuppeteerSharp- Memory grows with each operation
// Requires explicit browser recycling every N operations
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(); // Memory still accumulates!
}
// Must periodically: await browser.CloseAsync(); and re-launch

// ✅IronPDF- Stable memory, reuse renderer
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
}
// ❌PuppeteerSharp- Memory grows with each operation
// Requires explicit browser recycling every N operations
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(); // Memory still accumulates!
}
// Must periodically: await browser.CloseAsync(); and re-launch

// ✅IronPDF- Stable memory, reuse renderer
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
}
' ❌PuppeteerSharp- Memory grows with each operation
' Requires explicit browser recycling every N operations
For i As Integer = 0 To 999
    Dim page = Await browser.NewPageAsync()
    Await page.SetContentAsync($"<h1>Document {i}</h1>")
    Await page.PdfAsync($"doc_{i}.pdf")
    Await page.CloseAsync() ' Memory still accumulates!
Next
' Must periodically: Await browser.CloseAsync() and re-launch

' ✅IronPDF- Stable memory, reuse renderer
Dim renderer As New ChromePdfRenderer()
For i As Integer = 0 To 999
    Dim pdf = renderer.RenderHtmlAsPdf($"<h1>Document {i}</h1>")
    pdf.SaveAs($"doc_{i}.pdf")
    ' Memory managed automatically
Next
$vbLabelText   $csharpLabel

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;
    }
}
// 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;
    }
}
' Before (PuppeteerSharp - delete entire class)
Public Class PuppeteerBrowserPool
    Private ReadOnly _browsers As ConcurrentBag(Of IBrowser)
    Private ReadOnly _semaphore As SemaphoreSlim
    Private _operationCount As Integer
    ' ... recycling logic ...
End Class

' After (IronPDF - simple reuse)
Public Class PdfService
    Private ReadOnly _renderer As New ChromePdfRenderer()

    Public Function Generate(html As String) As Byte()
        Return _renderer.RenderHtmlAsPdf(html).BinaryData
    End Function
End Class
$vbLabelText   $csharpLabel

關鍵遷移注意事項

Async 到 Sync 的轉換

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: 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;
}
Imports System.Threading.Tasks
Imports PuppeteerSharp

' PuppeteerSharp: Async required
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
    Await (New BrowserFetcher()).DownloadAsync()
    Await Using browser = Await Puppeteer.LaunchAsync(...)
        Await Using page = Await browser.NewPageAsync()
            Await page.SetContentAsync(html)
            Return Await page.PdfDataAsync()
        End Using
    End Using
End Function

' IronPDF: Sync default
Public Function GeneratePdf(html As String) As Byte()
    Dim renderer = New ChromePdfRenderer()
    Return renderer.RenderHtmlAsPdf(html).BinaryData
End Function

' Or async when needed
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
    Dim renderer = New ChromePdfRenderer()
    Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
    Return pdf.BinaryData
End Function
$vbLabelText   $csharpLabel

邊際單位轉換

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;
//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;
MarginOptions = New MarginOptions With {
    .Top = "1in",      ' 25.4mm
    .Bottom = "0.75in", ' 19mm
    .Left = "1cm",     ' 10mm
    .Right = "20px"    ' ~7.5mm at 96dpi
}

renderer.RenderingOptions.MarginTop = 25    ' mm
renderer.RenderingOptions.MarginBottom = 19
renderer.RenderingOptions.MarginLeft = 10
renderer.RenderingOptions.MarginRight = 8
$vbLabelText   $csharpLabel

頁首/頁尾占位符轉換

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 pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
Dim pdf1 = renderer.RenderHtmlAsPdf(html1)
Dim pdf2 = renderer.RenderHtmlAsPdf(html2)
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("merged.pdf")
$vbLabelText   $csharpLabel

水印。

var watermark = new TextStamper
{
    Text = "CONFIDENTIAL",
    FontSize = 48,
    Opacity = 30,
    Rotation = -45
};
pdf.ApplyStamp(watermark);
var watermark = new TextStamper
{
    Text = "CONFIDENTIAL",
    FontSize = 48,
    Opacity = 30,
    Rotation = -45
};
pdf.ApplyStamp(watermark);
Dim watermark As New TextStamper With {
    .Text = "CONFIDENTIAL",
    .FontSize = 48,
    .Opacity = 30,
    .Rotation = -45
}
pdf.ApplyStamp(watermark)
$vbLabelText   $csharpLabel

密碼保護

pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.OwnerPassword = "admin"
pdf.SecuritySettings.UserPassword = "readonly"
pdf.SecuritySettings.AllowUserCopyPasteContent = False
$vbLabelText   $csharpLabel

數位簽名

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)
$vbLabelText   $csharpLabel

PDF/A 合規性

pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
$vbLabelText   $csharpLabel

效能比較摘要

指標 PuppeteerSharp IronPDF 改進
第一份 PDF (冷启動) 45s+ ~20s 速度快 55% 以上
後續 PDF 變數 一致性 可預測性
記憶體使用情況 500MB+ (成長中) ~50MB (穩定) 減少 90% 記憶體
磁碟空間 (Chromium) 300MB+ 0 消除下載
瀏覽器下載 要求 不需要 零設定
線程安全 限額 全文 可靠的並發性
PDF 生成時間 45s 20s 快55%

遷移清單

預遷移

  • 識別程式碼庫中所有PuppeteerSharp的使用情況
  • 文檔邊距值(將字串轉換為毫米)
  • 注意頁首/頁尾佔位符語法以進行轉換
  • 刪除瀏覽器池/回收基礎設施
  • ironpdf.com取得IronPDF許可證金鑰

套件變更

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

程式碼變更

  • 更新命名空間匯入
  • 刪除 BrowserFetcher.DownloadAsync() 調用
  • 移除 Puppeteer.LaunchAsync() 和瀏覽器管理
  • page.SetContentAsync() + page.PdfAsync() 替換為 RenderHtmlAsPdf()
  • page.GoToAsync() + page.PdfAsync() 替換為 RenderUrlAsPdf()
  • 將邊距字串轉換為毫米值
  • 轉換頁首/頁尾佔位符語法
  • 刪除所有瀏覽器/頁面銷毀程式碼
  • 刪除瀏覽器池基礎架構
  • 在應用程式啟動時新增許可證初始化

後遷移

  • PDF 輸出的視覺比較
  • 記憶體穩定性負載測試(應保持穩定,無需重新啟動)
  • 驗證頁首/頁尾的顯示是否正確,並顯示頁碼
  • 根據需要新增功能(安全性、浮水印、合併)

Curtis Chau
技術作家

Curtis Chau 擁有卡爾頓大學計算機科學學士學位,專注於前端開發,擅長於 Node.js、TypeScript、JavaScript 和 React。Curtis 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我