如何在 C# 中渲染 Azure Blob 儲存中的圖像
從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時造成了根本性問題:
-
首次使用前需要下載300MB+的Chromium。 PuppeteerSharp的一個顯著缺點是其龐大的部署大小,主要是由於捆綁的Chromium二進制文件。 這一龐大大小會讓Docker映像膨脹並在無伺服器環境中導致冷啟動問題。
-
載入時報告的記憶體增長需要手動回收瀏覽器。 在持續負載下,PuppeteerSharp使用者報告了跨瀏覽器實例的記憶體累積,通常需要通過人工程式回收來解決。
-
復雜的異步模式與瀏覽器生命周期管理。
-
列印至PDF輸出(相當於Ctrl+P,而不是螢幕截圖)。 布局可能會重新流動,背景可能預設會被省略,輸出是為列印而分頁的,而不是匹配瀏覽器視圖的。
-
不支持PDF/A或PDF/UA以滿足合規要求。 PuppeteerSharp無法生成符合PDF/A(歸檔)或PDF/UA(可存取性)規範的文件。
- 無PDF操作 - 僅生成,無合併/拆分/編輯功能。 雖然PuppeteerSharp在生成PDF方面很高效,但它缺乏進一步操作的能力,如合併、拆分、保護或編輯PDF。
PuppeteerSharp vs IronPDF比較
| 方面 | PuppeteerSharp | IronPDF |
|---|---|---|
| 主要目的 | 瀏覽器自動化 | PDF生成 |
| Chromium依賴 | 300MB+單獨下載 | 內建優化引擎 |
| API複雜性 | 異步瀏覽器/頁面生命周期 | 同步一行程式碼 |
| 初始化 | BrowserFetcher.DownloadAsync() + LaunchAsync |
new 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目標,這意味著它可以無阻礙相容地進入大多數現有應用程式。
開始之前
前提條件
- .NET環境:.NET Framework 4.6.2+ 或.NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet存取: 有能力安裝NuGet套件
- 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
# Remove PuppeteerSharp
dotnet remove package PuppeteerSharp
# Remove downloaded Chromium binaries (~300MB recovered)
# Delete the .local-chromium folder
# Add IronPDF
dotnet add package IronPdf
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"
完整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
核心API對應
| PuppeteerSharp API | IronPDFAPI | 注釋 |
|---|---|---|
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
之後(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
此範例說明基本的架構差異。 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");
}
}
// 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
之後(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
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"
}
});
}
}
// 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
之後(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
此範例展示了兩個程式庫之間的PDF選項映射。 PuppeteerSharp使用MarginOptions包含字串值 ("20mm")。 IronPDF使用RenderingOptions屬性,帶有直接紙張大小枚舉、方向枚舉和以毫米為單位的數值邊距值。
關鍵映射:
Format = PaperFormat.A4→PaperSize = PdfPaperSize.A4Landscape = true→PaperOrientation = PdfPaperOrientation.LandscapeMarginOptions.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
}
// 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
}
Imports PuppeteerSharp
Imports IronPdf
' PuppeteerSharp - memory growth typically requires periodic recycling
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()
Next
' Recommended: Await browser.CloseAsync() and re-launch every N operations
' IronPDF - reuse a single renderer across operations
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
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
關鍵遷移注意事項
異步到同步轉換
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
邊距單位轉換
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;
' PuppeteerSharp - string units
MarginOptions = New MarginOptions With {
.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類 | 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")
水印
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)
密碼保護
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
數位簽名
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)
PDF/A合規性
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
性能比較摘要
| 指標 | PuppeteerSharp | IronPDF | 改進 |
|---|---|---|---|
| 第一個PDF(冷啟動) | 45秒+ | 約20秒 | 快55%+ |
| 隨後的PDFs | 可變 | 一致 | 可預測 |
| 記憶體使用 | 500MB+(增長) | 約50MB(穩定) | 減少90%的記憶體 |
| 磁碟空間(Chromium) | 300MB+ | 0 | 消除下載 |
| 瀏覽器下載 | 必需的 | 不需要 | 零設定 |
| 執行緒安全 | 有限 | 全面 | 可靠的並發性 |
| PDF生成時間 | 45秒 | 20秒 | 快55% |
遷移檢查表
遷移前
- 識別程式碼庫中的所有PuppeteerSharp用法
- 文件邊距值(將字串轉換為毫米)
- 注意標頭/頁腳佔位符語法轉換
- 刪除瀏覽器池/回收基礎設施
- 獲取IronPDF授權金鑰來自ironpdf.com
套件變更
- 移除
PuppeteerSharpNuGet包 - 刪除
.local-chromium資料夾以回收約300MB磁碟空間 - 安裝
IronPdfNuGet包:dotnet add package IronPdf
程式碼變更
- 更新命名空間導入
- 移除
BrowserFetcher.DownloadAsync()調用 - 移除
Puppeteer.LaunchAsync()和瀏覽器管理 - 用
page.SetContentAsync()+RenderHtmlAsPdf() - 用
page.GoToAsync()+RenderUrlAsPdf() - 將邊距字串轉換為毫米值
- 轉換標頭/頁腳佔位符語法
- 移除所有的瀏覽器/頁面釋放程式碼
- 刪除瀏覽器池基礎設施
- 在應用程式啟動時新增授權初始化
遷移後
- PDF輸出的視覺比較
- 載入測試以確保記憶體穩定性(應無需回收仍保持穩定)
- 驗證標頭/頁腳渲染與頁碼的精確性
- 根據需要新增新功能(安全性、水印、合併)

