Como migrar do PuppeteerSharp para o IronPDF em C#
A migração do MarionetistaAfiado para o IronPDF transforma seu fluxo de trabalho de geração de PDFs, passando de uma ferramenta de automação de navegador com dependências de mais de 300 MB para uma biblioteca de PDFs desenvolvida especificamente para essa finalidade, com gerenciamento automático de memória. Este guia fornece um caminho de migração completo, passo a passo, que elimina os downloads do Chromium, resolve problemas de vazamento de memória e oferece recursos abrangentes de manipulação de PDFs.
Por que migrar do MarionetistaAfiado para o IronPDF?
Entendendo o PuppeteerSharp
PuppeteerSharp é uma versão .NET do Puppeteer do Google, que traz recursos de automação de navegador para C#. Ele gera PDFs usando a funcionalidade integrada de impressão para PDF do Chrome — o mesmo que pressionar Ctrl+P em um navegador. Isso produz um resultado pronto para impressão, otimizado para papel, que difere do que você vê na tela.
O MarionetistaAfiado foi projetado para testes e extração de dados da web, não para geração de documentos. Embora seja uma ferramenta capaz, o uso do MarionetistaAfiado para geração de PDFs apresenta desafios significativos de produção.
O problema da automação do navegador
O MarionetistaAfiado foi projetado para automação de navegadores, não para geração de documentos. Isso cria problemas fundamentais ao usá-lo com PDFs:
-
É necessário fazer o download do Chromium (mais de 300 MB) antes do primeiro uso. Uma desvantagem significativa do MarionetistaAfiado é o seu tamanho de implantação considerável, principalmente devido ao binário do Chromium que ele inclui. Esse tamanho considerável pode inflar as imagens do Docker e causar problemas de inicialização a frio em ambientes sem servidor.
-
Vazamentos de memória sob carga que exigem reinicialização manual do navegador. Sob carga pesada, o MarionetistaAfiado é conhecido por apresentar vazamentos de memória. O acúmulo de memória pelas instâncias do navegador exige intervenção manual para o gerenciamento e a reciclagem do processo.
-
Padrões assíncronos complexos com gerenciamento do ciclo de vida do navegador.
-
Impressão em PDF (equivalente a Ctrl+P, não captura de tela). Os layouts podem ser redimensionados, os planos de fundo podem ser omitidos por padrão e a saída é paginada para impressão em vez de corresponder à área visível do navegador.
-
Não há suporte para PDF/A ou PDF/UA para atender aos requisitos de conformidade. O MarionetistaAfiado não consegue gerar documentos compatíveis com PDF/A (arquivísticos) ou PDF/UA (acessíveis).
- Sem manipulação de PDF - apenas geração, sem mesclagem/divisão/edição. Embora o MarionetistaAfiado seja eficiente na geração de PDFs, ele carece de recursos para manipulação adicional, como mesclagem, divisão, proteção ou edição de PDFs.
Comparação entre MarionetistaAfiado e IronPDF
| Aspecto | MarionetistaAfiado | IronPDF |
|---|---|---|
| Objetivo principal | Automação do navegador | Geração de PDF |
| Dependência do Chromium | Download separado de mais de 300 MB | Motor otimizado integrado |
| Complexidade da API | Ciclo de vida assíncrono do navegador/página | Frases curtas síncronas |
| Inicialização | BrowserFetcher.DownloadAsync() + LaunchAsync |
new ChromePdfRenderer() |
| Gerenciamento de memória | Reciclagem manual do navegador necessária | Automático |
| Memória sob carga | Mais de 500 MB com vazamentos | ~50MB estável |
| Partida a frio | 45+ segundos | ~20 segundos |
| Suporte PDF/A | Não disponível | Apoiado |
| Acessibilidade PDF/UA | Não disponível | Apoiado |
| Edição de PDF | Não disponível | Mesclar, dividir, carimbar, editar |
| Assinaturas digitais | Não disponível | Apoiado |
| Segurança da rosca | Limitado | Completo |
| Suporte profissional | Comunidade | Comercial com SLA |
Suporte da plataforma
| Biblioteca | .NET Framework 4.7.2 | .NET Core 3.1 | .NET 6-8 | .NET 10 | | --------- | :---: | :---: | :---: | :---: || IronPDF | Completo | Completo | Completo | Completo || MarionetistaAfiado | Limitado | Completo | Completo | Pendente | O amplo suporte do IronPDF em plataformas .NET garante que os desenvolvedores possam utilizá-lo em diversos ambientes sem encontrar problemas de compatibilidade, oferecendo uma opção flexível para aplicações .NET modernas até 2025 e 2026.
Antes de começar
Pré-requisitos
- Ambiente .NET : .NET Framework 4.6.2+ ou .NET Core 3.1+ / .NET 5/6/7/8/9+
- Acesso ao NuGet : Capacidade de instalar pacotes NuGet.
- Licença do IronPDF : Obtenha sua chave de licença em IronPDF
Alterações no pacote 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
Não é necessário nenhum BrowserFetcher.DownloadAsync() com o IronPDF - o mecanismo de renderização já está incluído automaticamente.
Configuração de licença
// 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"
Referência completa da API
Alterações de namespace
// 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
Mapeamentos da API principal
| API MarionetistaAfiado | API IronPDF | Notas |
|---|---|---|
new BrowserFetcher().DownloadAsync() |
Não é necessário | Sem download no navegador |
Puppeteer.LaunchAsync(options) |
Não é necessário | Sem gerenciamento de navegador |
browser.NewPageAsync() |
Não é necessário | Sem contexto de página |
page.GoToAsync(url) |
renderer.RenderUrlAsPdf(url) |
Renderização direta |
page.SetContentAsync(html) |
renderer.RenderHtmlAsPdf(html) |
Renderização direta |
page.PdfAsync(path) |
pdf.SaveAs(path) |
Após a renderização |
await page.CloseAsync() |
Não é necessário | Limpeza automática |
await browser.CloseAsync() |
Não é necessário | Limpeza automática |
PdfOptions.Format |
RenderingOptions.PaperSize |
Tamanho do papel |
PdfOptions.Landscape |
RenderingOptions.PaperOrientation |
Orientação |
PdfOptions.MarginOptions |
RenderingOptions.MarginTop/Bottom/Left/Right |
margens individuais |
PdfOptions.PrintBackground |
RenderingOptions.PrintHtmlBackgrounds |
Impressão de fundo |
PdfOptions.HeaderTemplate |
RenderingOptions.HtmlHeader |
Cabeçalhos HTML |
PdfOptions.FooterTemplate |
RenderingOptions.HtmlFooter |
Rodapés HTML |
page.WaitForSelectorAsync() |
RenderingOptions.WaitFor.HtmlElementId |
Aguarde o elemento |
Exemplos de migração de código
Exemplo 1: Conversão básica de HTML para PDF
Antes (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
Após (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
Este exemplo demonstra a diferença arquitetônica fundamental. O MarionetistaAfiado requer seis operações assíncronas: BrowserFetcher.DownloadAsync() (download do Chromium de mais de 300 MB), Puppeteer.LaunchAsync(), browser.NewPageAsync(), page.SetContentAsync() e page.PdfAsync(), além do descarte adequado com await using.
IronPDF elimina toda essa complexidade: crie um ChromePdfRenderer, chame RenderHtmlAsPdf() e SaveAs(). Sem padrões assíncronos, sem ciclo de vida do navegador, sem downloads do Chromium. A abordagem do IronPDF oferece uma sintaxe mais limpa e melhor integração com aplicativos .NET modernos. Consulte a documentação de conversão de HTML para PDF para obter exemplos completos.
Exemplo 2: Conversão de URL para PDF
Antes (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
Após (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
O MarionetistaAfiado usa GoToAsync() para navegar até um URL seguido por PdfAsync(). IronPDF fornece um único método RenderUrlAsPdf() que lida com a navegação e a geração de PDF em uma única chamada. Saiba mais em nossos tutoriais .
Exemplo 3: Configurações de página personalizadas com margens
Antes (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
Após (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
Este exemplo mostra como as opções de PDF são mapeadas entre as duas bibliotecas. MarionetistaAfiado usa PdfOptions com Format, Landscape e MarginOptions contendo valores de string ("20mm"). O IronPDF usa propriedades RenderingOptions com enumerações diretas de tamanho de papel, enumerações de orientação e valores numéricos de margem em milímetros.
Mapeamentos de teclas:
Format = PaperFormat.A4→PaperSize = PdfPaperSize.A4Landscape = true→PaperOrientation = PdfPaperOrientation.LandscapeMarginOptions.Top = "20mm"→MarginTop = 20(milímetros numéricos)
O problema do vazamento de memória
O MarionetistaAfiado é conhecido por acumular memória sob carga contínua:
// ❌ MarionetistaAfiado - 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
}
// ❌ MarionetistaAfiado - 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
}
' ❌ MarionetistaAfiado - 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
O IronPDF elimina a necessidade da infraestrutura de agrupamento de navegadores exigida pelo 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
Notas críticas sobre migração
Conversão de assíncrono para síncrono
O MarionetistaAfiado requer async/await em todas as suas etapas; O IronPDF suporta operações síncronas:
// 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
Conversão de Unidades de Margem
PuppeteerSharp usa unidades de corda; O IronPDF usa milímetros numéricos:
// MarionetistaAfiado - 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;
// MarionetistaAfiado - 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;
' MarionetistaAfiado - 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
Conversão de espaços reservados para cabeçalho/rodapé
| Marionetista Classe Afiada | Espaço reservado para IronPDF |
|---|---|
<span class='pageNumber'> |
{page} |
<span class='totalPages'> |
{total-pages} |
<span class='date'> |
{date} |
<span class='title'> |
{html-title} |
Novas funcionalidades após a migração
Após migrar para o IronPDF, você obtém recursos que o MarionetistaAfiado não pode fornecer:
Fusão de PDFs
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")
Marcas d'água
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)
Proteção por senha
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
Assinaturas digitais
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)
Conformidade com PDF/A
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
Resumo da comparação de desempenho
| Métrica | MarionetistaAfiado | IronPDF | Melhoria |
|---|---|---|---|
| Primeiro PDF (Inicialização a frio) | 45s+ | ~20s | 55% mais rápido |
| PDFs subsequentes | Variável | Consistente | Previsível |
| Uso de memória | Mais de 500 MB (e continua crescendo) | ~50 MB (estável) | 90% menos memória |
| Espaço em disco (Chromium) | 300 MB ou mais | 0 | Eliminar downloads |
| Download do navegador | Obrigatório | Não é necessário | Configuração zero |
| Segurança da rosca | Limitado | Completo | Concorrência confiável |
| Tempo de geração do PDF | 45s | anos 20 | 55% mais rápido |
Lista de verificação para migração
Pré-migração
- Identificar todas as utilizações do MarionetistaAfiado na base de código.
- Valores de margem do documento (converter strings em milímetros)
- Observe a sintaxe dos espaços reservados para cabeçalho/rodapé para conversão.
- Eliminar a infraestrutura de agrupamento/reciclagem de navegadores
- Obtenha a chave de licença do IronPDF em IronPDF
Alterações no pacote
- Remover o pacote NuGet
PuppeteerSharp - Exclua a pasta
.local-chromiumpara recuperar aproximadamente 300 MB de espaço em disco. - Instale o pacote NuGet
IronPdf:dotnet add package IronPdf
Alterações no código
- Atualizar importações de namespace
- Remover chamadas
BrowserFetcher.DownloadAsync() - Remover
Puppeteer.LaunchAsync()e gerenciamento do navegador - Substitua
page.SetContentAsync()+page.PdfAsync()porRenderHtmlAsPdf() - Substitua
page.GoToAsync()+page.PdfAsync()porRenderUrlAsPdf() - Converter strings de margem em valores em milímetros
- Converter sintaxe de espaço reservado de cabeçalho/rodapé
- Remover todos os códigos de descarte de navegador/página
- Excluir a infraestrutura de agrupamento de navegadores
- Adicionar inicialização de licença na inicialização do aplicativo
Pós-migração
- Comparação visual da saída em PDF
- Teste de carga para estabilidade da memória (deve permanecer estável sem reinicialização)
- Verificar a renderização do cabeçalho/rodapé com os números de página
- Adicionar novas funcionalidades (segurança, marcas d'água, mesclagem) conforme necessário.

