跳過到頁腳內容
MIGRATION GUIDES

How to Migrate from Playwright to IronPDF in C#

從 劇作家 for .NET 遷移到 IronPDF 會將您的 PDF 產生工作流程從以測試為中心的瀏覽器自動化工具轉變為專用的 PDF 庫。 本指南提供了一條完整的、循序漸進的遷移路徑,消除了複雜的非同步模式、瀏覽器生命週期管理和 400MB 以上的瀏覽器下載,同時提供了更好的效能和專業的 PDF 功能。

為什麼要從 劇作家 遷移到 IronPDF

了解 .NET 的 Playwright

Playwright for .NET 是微軟瀏覽器自動化工具系列的一部分; 它的結構圍繞著提供跨 Chromium、Firefox 和 WebKit 的全面測試功能而建構。 該庫採用"測試優先"的設計理念,這意味著它的主要關注點是涉及基於瀏覽器的測試場景。 雖然 劇作家 支援產生 PDF 文件,但此功能更像是一種補充功能,並不像專用 PDF 工具那樣提供精細的配置。

Playwright for .NET 主要是一個瀏覽器自動化和測試框架,PDF 生成只是其輔助功能。 與 PuppeteerSharp 類似,Playwright 使用瀏覽器的"列印到 PDF"功能產生 PDF 檔案——相當於按下 Ctrl+P。這樣生成的輸出檔案針對紙張進行了最佳化,可以直接用於列印,這與螢幕渲染有所不同。

測試框架問題

Playwright 的設計初衷是用於端對端測試,而不是產生文件。 這會為使用 PDF 文件帶來根本性問題:

  1. 首次使用前需下載 400MB 以上的瀏覽器檔案。 劇作家 的預設配置涉及下載多個瀏覽器,這對於資源受限的環境來說可能是一個需要考慮的問題。

  2. 具有瀏覽器上下文和頁面管理的複雜非同步模式。 開發人員必須熟悉瀏覽器上下文和頁面管理,以及正確的資源釋放方法。

3.測試優先架構不針對文件產生進行最佳化。

4.列印到 PDF 的限制與 Ctrl+P 瀏覽器列印相同。 佈局可能會重新排版,背景預設可能會省略,並且輸出會分頁以便列印。

5.不支援 PDF/A 或 PDF/UA無障礙存取。 劇作家無法製作符合 PDF/A(存檔)或 PDF/UA(無障礙)標準的文件。 對於第 508 條款、歐盟無障礙指令或長期存檔要求,您需要一個專門的 PDF 庫。

  1. 需要完整瀏覽器執行個體的資源密集型操作

劇作家 與 IronPDF 效能比較

指標 劇作家 IronPDF
主要目的 瀏覽器測試 PDF生成
瀏覽器下載 400MB+(Chromium、Firefox、WebKit) 內建優化引擎
首次渲染(冷啟動) 4.5秒 2.8秒
後續渲染 3.8-4.1秒 0.8-1.2秒
每次轉換的記憶體 280-420MB 80-120MB
API複雜度 非同步瀏覽器/上下文/頁面生命週期 同步單句
初始化 playwright install + CreateAsync + LaunchAsync new ChromePdfRenderer()
PDF/A 支持 無法使用 全力支持
PDF/UA 無障礙訪問 無法使用 全力支持
數位簽名 無法使用 全力支持
PDF編輯 無法使用 合併、拆分、蓋章、編輯
專業支援 社群 商業服務水準協議

IronPDF 的設計初衷是專注於 PDF 生成。 與以測試為中心的 劇作家 不同,IronPDF 提供了各種以文件為中心的 API 功能。 它依賴一個經過最佳化的 Chromium 實例,注重效率,並提供同步和非同步操作。 這為需要 PDF 功能的開發人員簡化了思維模型和工作流程。

對於計劃在 2025 年和 2026 年採用 .NET 10 和 C# 14 的團隊,IronPDF 提供了一個專門構建的 PDF 解決方案,該方案消除了瀏覽器自動化開銷,同時提供了更好的性能和專業的文檔功能。


開始之前

先決條件

  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 Playwright
dotnet remove package Microsoft.Playwright

# Remove browser binaries (reclaim ~400MB disk space)
# Delete the .playwright folder in your project or user directory

# Add IronPDF
dotnet add package IronPdf
# Remove Playwright
dotnet remove package Microsoft.Playwright

# Remove browser binaries (reclaim ~400MB disk space)
# Delete the .playwright folder in your project or user directory

# Add IronPDF
dotnet add package IronPdf
SHELL

使用 IronPDF 無需playwright install ,渲染引擎會自動捆綁。

許可證配置

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

完整 API 參考

命名空間變更

// Before: Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
$vbLabelText   $csharpLabel

核心 API 映射

劇作家 API IronPDF API 筆記
Playwright.CreateAsync() new ChromePdfRenderer() 無需異步
playwright.Chromium.LaunchAsync() 不需要 無瀏覽器管理
browser.NewPageAsync() 不需要 無頁面上下文
page.GotoAsync(url) renderer.RenderUrlAsPdf(url) 直接 URL 渲染
page.SetContentAsync(html) + page.PdfAsync() renderer.RenderHtmlAsPdf(html) 單方法
page.CloseAsync() 不需要 自動清理
browser.CloseAsync() 不需要 自動清理
PagePdfOptions.Format RenderingOptions.PaperSize 紙張尺寸
PagePdfOptions.Margin RenderingOptions.MarginTop/Bottom/Left/Right 個人利潤
PagePdfOptions.DisplayHeaderFooter RenderingOptions.TextHeader / TextFooter 頁首/頁尾
PagePdfOptions.HeaderTemplate RenderingOptions.HtmlHeader HTML 頭部
PagePdfOptions.FooterTemplate RenderingOptions.HtmlFooter HTML頁腳
<span class="pageNumber"> {page} 頁碼佔位符

程式碼遷移範例

範例 1:HTML 字串到 PDF 的轉換

之前(劇作家):

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

class Program
{
    static async Task Main(string[] args)
    {
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();

        string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
        await page.SetContentAsync(html);
        await page.PdfAsync(new PagePdfOptions { Path = "output.pdf" });

        await browser.CloseAsync();
    }
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();

        string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
        await page.SetContentAsync(html);
        await page.PdfAsync(new PagePdfOptions { Path = "output.pdf" });

        await browser.CloseAsync();
    }
}
$vbLabelText   $csharpLabel

(IronPDF 之後):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
    }
}
$vbLabelText   $csharpLabel

這個例子展示了架構上的根本差異。 劇作家 需要五個非同步操作: Playwright.CreateAsync()Chromium.LaunchAsync()NewPageAsync()SetContentAsync()PdfAsync() ,以及使用CloseAsync()進行明確瀏覽器清理。

IronPDF 消除了所有這些複雜性:建立一個ChromePdfRenderer ,呼叫RenderHtmlAsPdf() ,然後SaveAs() 。 沒有非同步模式,沒有瀏覽器生命週期,沒有清理程式碼。 IronPDF 的方法提供了更簡潔的語法和與現代 .NET 應用程式更好的整合。 請參閱HTML 轉 PDF 文件以取得完整範例。

範例 2:URL 轉 PDF

之前(劇作家):

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

class Program
{
    static async Task Main(string[] args)
    {
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();

        await page.GotoAsync("https://www.example.com");
        await page.PdfAsync(new PagePdfOptions 
        { 
            Path = "webpage.pdf",
            Format = "A4"
        });

        await browser.CloseAsync();
    }
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();

        await page.GotoAsync("https://www.example.com");
        await page.PdfAsync(new PagePdfOptions 
        { 
            Path = "webpage.pdf",
            Format = "A4"
        });

        await browser.CloseAsync();
    }
}
$vbLabelText   $csharpLabel

(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");
    }
}
$vbLabelText   $csharpLabel

Playwright 使用GotoAsync()導覽至 URL,然後使用PdfAsync() 。 IronPDF 提供了一個RenderUrlAsPdf()方法,該方法可在一個呼叫中處理導覽和 PDF 產生。 請注意,Playwright 需要在PagePdfOptions中指定Format ,而 IronPDF 使用RenderingOptions.PaperSize進行紙張大小配置。 了解更多信息,請閱讀我們的教程

範例 3:自訂頁面尺寸和邊距

之前(劇作家):

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

class Program
{
    static async Task Main()
    {
        using var playwright = await Playwright.CreateAsync();
        await using var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();
        await page.SetContentAsync("<h1>Custom PDF</h1><p>Letter size with margins</p>");
        await page.PdfAsync(new PagePdfOptions 
        { 
            Path = "custom.pdf",
            Format = "Letter",
            Margin = new Margin { Top = "1in", Bottom = "1in", Left = "0.5in", Right = "0.5in" }
        });
    }
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using var playwright = await Playwright.CreateAsync();
        await using var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();
        await page.SetContentAsync("<h1>Custom PDF</h1><p>Letter size with margins</p>");
        await page.PdfAsync(new PagePdfOptions 
        { 
            Path = "custom.pdf",
            Format = "Letter",
            Margin = new Margin { Top = "1in", Bottom = "1in", Left = "0.5in", Right = "0.5in" }
        });
    }
}
$vbLabelText   $csharpLabel

(IronPDF 之後):

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

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
        renderer.RenderingOptions.MarginTop = 25;
        renderer.RenderingOptions.MarginBottom = 25;
        renderer.RenderingOptions.MarginLeft = 12;
        renderer.RenderingOptions.MarginRight = 12;
        var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Letter size with margins</p>");
        pdf.SaveAs("custom.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
        renderer.RenderingOptions.MarginTop = 25;
        renderer.RenderingOptions.MarginBottom = 25;
        renderer.RenderingOptions.MarginLeft = 12;
        renderer.RenderingOptions.MarginRight = 12;
        var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Letter size with margins</p>");
        pdf.SaveAs("custom.pdf");
    }
}
$vbLabelText   $csharpLabel

Playwright 使用基於字串的邊距值( &quot;1in&quot;&quot;0.5in&quot; ),而 IronPDF 則使用數值毫米值。 換算關係為:1 英吋 = 25.4 毫米,所以&quot;1in&quot;變成25&quot;0.5in&quot;變成大約12 。 劇作家Format = &quot;Letter&quot;對應到 IronPDF 的PaperSize = PdfPaperSize.Letter

範例 4:頁首、頁尾和自訂設置

之前(劇作家):

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

class Program
{
    static async Task Main(string[] args)
    {
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();

        string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
        await page.SetContentAsync(html);

        await page.PdfAsync(new PagePdfOptions
        {
            Path = "custom.pdf",
            Format = "A4",
            Margin = new Margin { Top = "1cm", Bottom = "1cm", Left = "1cm", Right = "1cm" },
            DisplayHeaderFooter = true,
            HeaderTemplate = "<div style='font-size:10px; text-align:center;'>Header</div>",
            FooterTemplate = "<div style='font-size:10px; text-align:center;'>Page <span class='pageNumber'></span></div>"
        });

        await browser.CloseAsync();
    }
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();

        string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
        await page.SetContentAsync(html);

        await page.PdfAsync(new PagePdfOptions
        {
            Path = "custom.pdf",
            Format = "A4",
            Margin = new Margin { Top = "1cm", Bottom = "1cm", Left = "1cm", Right = "1cm" },
            DisplayHeaderFooter = true,
            HeaderTemplate = "<div style='font-size:10px; text-align:center;'>Header</div>",
            FooterTemplate = "<div style='font-size:10px; text-align:center;'>Page <span class='pageNumber'></span></div>"
        });

        await browser.CloseAsync();
    }
}
$vbLabelText   $csharpLabel

(IronPDF 之後):

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

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 10;
        renderer.RenderingOptions.MarginRight = 10;
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.TextHeader.CenterText = "Header";
        renderer.RenderingOptions.TextFooter.CenterText = "Page {page}";

        string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        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.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 10;
        renderer.RenderingOptions.MarginRight = 10;
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.TextHeader.CenterText = "Header";
        renderer.RenderingOptions.TextFooter.CenterText = "Page {page}";

        string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("custom.pdf");
    }
}
$vbLabelText   $csharpLabel

此範例展示了頁首/頁尾佔位符語法的差異。 劇作家 使用基於 HTML 類別的佔位符(<span class="pageNumber"></span> ),而 IronPDF 則使用花括號佔位符( {page} )。 請注意,Playwright 需要DisplayHeaderFooter = true才能啟用頁首/頁腳,而 IronPDF 會在您設定頁首/頁尾內容時自動啟用它們。


關鍵遷移說明

異步到同步轉換

Playwright 需全程使用 async/await; IronPDF 支援同步操作:

// Playwright: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
    using var playwright = await Playwright.CreateAsync();
    await using var browser = await playwright.Chromium.LaunchAsync();
    var page = await browser.NewPageAsync();
    await page.SetContentAsync(html);
    return await page.PdfAsync();
}

// IronPDF: Sync is simpler
public byte[] GeneratePdf(string html)
{
    var renderer = new ChromePdfRenderer();
    return renderer.RenderHtmlAsPdf(html).BinaryData;
}
// Playwright: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
    using var playwright = await Playwright.CreateAsync();
    await using var browser = await playwright.Chromium.LaunchAsync();
    var page = await browser.NewPageAsync();
    await page.SetContentAsync(html);
    return await page.PdfAsync();
}

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

邊際單位轉換

劇作家運用弦樂單元; IronPDF 使用數值毫米:

劇作家 IronPDF(毫米)
"1in" 25
"0.5in" 12
"1cm" 10

頁首/頁尾佔位符轉換

劇作家班 IronPDF佔位符
<span class="pageNumber"> {page}
<span class="totalPages"> {total-pages}
<span class="date"> {date}
<span class="title"> {html-title}

瀏覽器生命週期消除

移除所有瀏覽器管理程式碼:

// Playwright: Explicit cleanup required
await page.CloseAsync();
await browser.CloseAsync();
playwright.Dispose();

// IronPDF: No disposal needed - just use the renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Playwright: Explicit cleanup required
await page.CloseAsync();
await browser.CloseAsync();
playwright.Dispose();

// IronPDF: No disposal needed - just use the renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
$vbLabelText   $csharpLabel

遷移後的新功能

移轉到 IronPDF 後,您將獲得 劇作家 無法提供的功能:

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");
$vbLabelText   $csharpLabel

水印

pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
$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;
$vbLabelText   $csharpLabel

數位簽名

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var 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);
$vbLabelText   $csharpLabel

遷移清單

遷移前

  • 識別所有 劇作家 PDF 產生程式碼
  • 文檔邊距值(將英吋/公分轉換為毫米)
  • 注意頁首/頁尾佔位符語法以進行轉換
  • ironpdf.com取得 IronPDF 許可證金鑰

軟體包變更

  • 刪除Microsoft.Playwright NuGet 套件
  • 刪除.playwright資料夾回收約 400MB 磁碟空間 安裝IronPdf NuGet 套件: dotnet add package IronPdf

程式碼更改

  • 更新命名空間匯入
  • 使用ChromePdfRenderer取代非同步瀏覽器生命週期
  • page.SetContentAsync() + page.PdfAsync()轉換為RenderHtmlAsPdf()
  • page.GotoAsync() + page.PdfAsync()轉換為RenderUrlAsPdf()
  • 將邊距字串轉換為毫米值
  • 轉換頁首/頁尾佔位符語法
  • 刪除所有瀏覽器/頁面銷毀程式碼
  • 在應用程式啟動時新增許可證初始化

移民後

  • PDF 輸出的視覺比較
  • 驗證頁首/頁尾的顯示是否正確,並顯示頁碼
  • 測試頁邊距和頁面尺寸的準確性
  • 根據需要新增功能(安全性、浮水印、合併)

Curtis Chau
技術撰稿人

Curtis Chau 擁有電腦科學學士學位(卡爾頓大學),專長於前端開發,精通 Node.js、TypeScript、JavaScript 和 React。Curtis 對製作直覺且美觀的使用者介面充滿熱情,他喜歡使用現代化的架構,並製作結構良好且視覺上吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 也有濃厚的興趣,他喜歡探索整合硬體與軟體的創新方式。在空閒時間,他喜歡玩遊戲和建立 Discord bots,將他對技術的熱愛與創意結合。