Saltar al pie de página
GUíAS DE MIGRACIóN

Migrar de PuppeteerSharp a IronPDF: VeriFactu, LOPDGDD y TicketBAI sin Fugas de Memoria

La migración de PuppeteerSharp a IronPDF transforma su flujo de trabajo de generación de PDF de una herramienta de automatización del navegador con dependencias de más de 300 MB a una biblioteca PDF creada específicamente con gestión automática de memoria. Para los ISVs y desarrolladores españoles, PuppeteerSharp introduce riesgos regulatorios y técnicos específicos en flujos de facturación electrónica:

Riesgos VeriFactu (Real Decreto-Ley 15/2025): El output print-to-PDF de PuppeteerSharp (equivalente a Ctrl+P) puede omitir fondos y bordes por defecto, comprometiendo la renderización de la leyenda VERI*FACTU y el QR de la AEAT con el patrón de verificación requerido por la AEAT.

Riesgos TicketBAI: PuppeteerSharp no soporta firmas digitales XAdES requeridas por TicketBAI en Bizkaia, Gipuzkoa y Araba. IronPDF incluye firma nativa.

Riesgos LOPDGDD y AEPD: Las fugas de memoria conocidas de PuppeteerSharp bajo carga sostenida pueden comprometer la estabilidad de servidores de facturación. La AEPD exige que los sistemas de tratamiento de datos personales —incluyendo datos de facturas— implementen medidas técnicas adecuadas de integridad y disponibilidad.

Riesgos Facturae/FACe: PuppeteerSharp no soporta PDF/A requerido para Facturae XML en la plataforma FACe del sector público. La Ley Crea y Crece exige este formato a partir de 2027.

Las penalizaciones para proveedores de software de facturación no conformes con VeriFactu alcanzan los 150.000 €/año según la AEAT.

Por qué migrar de PuppeteerSharp a IronPDF en España

Entendiendo PuppeteerSharp

PuppeteerSharp es una adaptación a .NET de Puppeteer de Google, que lleva las capacidades de automatización del navegador a C#. Genera archivos PDF utilizando la función integrada de impresión a PDF de Chrome, igual que si pulsaras Ctrl+P en un navegador. El resultado es un documento listo para imprimir y optimizado para el papel, que difiere de lo que se ve en pantalla.

PuppeteerSharp se diseñó para pruebas web y scraping, no para la generación de documentos. Aunque es capaz, el uso de PuppeteerSharppara la generación de PDF crea importantes retos de producción.

El problema de la automatización del navegador

PuppeteerSharp se diseñó para la automatización de navegadores, no para la generación de documentos. Esto plantea problemas fundamentales cuando se utiliza para PDF:

  1. se requieren 300MB+ de descargas de Chromium antes del primer uso. Una desventaja significativa de PuppeteerSharpes su gran tamaño de despliegue, debido principalmente al binario Chromium que incluye. Este tamaño considerable puede inflar las imágenes de Docker y causar problemas de arranque en frío en entornos sin servidor.

  2. Fugas de memoria bajo carga que requieren el reciclaje manual del navegador. Bajo carga pesada, PuppeteerSharpes conocido por experimentar fugas de memoria. La acumulación de memoria por parte de las instancias del navegador hace necesaria la intervención manual para la gestión y el reciclaje del proceso.

  3. Patrones async complejos con gestión del ciclo de vida del navegador.

  4. Print-to-PDF output (equivalente a Ctrl+P, no captura de pantalla). Los diseños pueden refluir, los fondos pueden omitirse por defecto y el resultado se pagina para la impresión en lugar de ajustarse a la ventana del navegador.

  5. No es compatible con PDF/A ni PDF/UA por requisitos de conformidad. PuppeteerSharpno puede producir documentos PDF/A (archivo) o PDF/UA (accesibilidad).

  6. Sin manipulación de PDF - sólo generación, sin fusión/división/edición. Aunque PuppeteerSharpes eficiente a la hora de generar archivos PDF, carece de capacidades para su manipulación posterior, como combinar, dividir, proteger o editar archivos PDF.

Comparación entre PuppeteerSharpy IronPDF

Aspecto PuppeteerSharp IronPDF
Finalidad principal Automatización de navegadores Generación de PDF
Dependencia de Chromium descarga separada de más de 300 MB Motor integrado optimizado
Complejidad de la API Ciclo de vida asíncrono de navegador/página Sincronización de frases
Inicialización BrowserFetcher.DownloadAsync() + Lanzamiento asíncrono new ChromePdfRenderer()
Gestión de memoria Se requiere reciclaje manual del navegador Automático
Memoria bajo carga más de 500 MB con filtraciones ~50 MB estables
Inicio en frío más de 45 segundos ~20 segundos
Soporte PDF/A No disponible Se admite
Accesibilidad PDF/UA No disponible Se admite
Edición de PDF No disponible Combinar, dividir, sellar, editar
Firmas digitales No disponible Se admite
Seguridad de hilos Limitado Completo
Soporte profesional Comunidad Comercial con SLA

Soporte de plataforma

| Biblioteca | .NET Framework 4.7.2| .NET Core 3.1| .NET 6-8| .NET 10| | --------- | :---: | :---: | :---: | :---: ||IronPDF| Completo | Completo | Completo | Completo || PuppeteerSharp| Limitado | Completo | Completo | Pendiente | La amplia compatibilidad deIronPDFcon todas las plataformas .NET garantiza que los desarrolladores puedan utilizarlo en varios entornos sin encontrar problemas de compatibilidad, lo que proporciona una opción flexible para las aplicaciones .NET modernas hasta 2025 y 2026.


Antes de empezar

Prerrequisitos

  1. Entorno .NET : .NET Framework 4.6.2+ o .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. Acceso a NuGet : Capacidad para instalar paquetes NuGet
  3. Licencia deIronPDF: Obtenga su clave de licencia en IronPDF

Cambios en el paquete 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

No se requiere BrowserFetcher.DownloadAsync() con IronPDF : el motor de renderizado se incluye automáticamente.

Configuración de licencias

// 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

Referencia completa de la API

Cambios en el espacio de nombres

// 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

Mapeos de API principales

API de PuppeteerSharp API de IronPDF Notas
new BrowserFetcher().DownloadAsync() No es necesario Sin descarga de navegador
Puppeteer.LaunchAsync(options) No es necesario Sin gestión de navegador
browser.NewPageAsync() No es necesario Sin contexto de página
page.GoToAsync(url) renderer.RenderUrlAsPdf(url) Traducción directa
page.SetContentAsync(html) renderer.RenderHtmlAsPdf(html) Traducción directa
page.PdfAsync(path) pdf.SaveAs(path) Después de la traducción
await page.CloseAsync() No es necesario Limpieza automática
await browser.CloseAsync() No es necesario Limpieza automática
PdfOptions.Format RenderingOptions.PaperSize Tamaño del papel
PdfOptions.Landscape RenderingOptions.PaperOrientation Orientación
PdfOptions.MarginOptions RenderingOptions.MarginTop/Bottom/Left/Right Márgenes individuales
PdfOptions.PrintBackground RenderingOptions.PrintHtmlBackgrounds Impresión de fondo
PdfOptions.HeaderTemplate RenderingOptions.HtmlHeader Encabezados HTML
PdfOptions.FooterTemplate RenderingOptions.HtmlFooter Pies de página HTML
page.WaitForSelectorAsync() RenderingOptions.WaitFor.HtmlElementId Esperar elemento

Ejemplos de migración de código

Ejemplo 1: Conversión básica de HTML a 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
$vbLabelText   $csharpLabel

Despué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
$vbLabelText   $csharpLabel

Este ejemplo demuestra la diferencia arquitectónica fundamental. PuppeteerSharprequiere seis operaciones asincrónicas: BrowserFetcher.DownloadAsync() (descarga de Chromium de más de 300 MB), Puppeteer.LaunchAsync(), browser.NewPageAsync(), page.SetContentAsync() y page.PdfAsync(), además de la eliminación adecuada con await using.

IronPDF elimina toda esta complejidad: crea un ChromePdfRenderer, llama a RenderHtmlAsPdf() y SaveAs(). Ni patrones asíncronos, ni ciclo de vida del navegador, ni descargas de Chromium. El enfoque deIronPDFofrece una sintaxis más limpia y una mejor integración con las aplicaciones .NET modernas. Consulte la documentación HTML a PDF para ver ejemplos completos.

Ejemplo 2: Conversión de URL a 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
$vbLabelText   $csharpLabel

Despué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
$vbLabelText   $csharpLabel

PuppeteerSharp usa GoToAsync() para navegar a una URL seguida de PdfAsync().IronPDFproporciona un único método RenderUrlAsPdf() que maneja la navegación y la generación de PDF en una sola llamada. Más información en nuestros tutoriales.

Ejemplo 3: Configuración de página personalizada con márgenes

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
$vbLabelText   $csharpLabel

Despué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
$vbLabelText   $csharpLabel

Este ejemplo muestra la correspondencia entre las opciones PDF de las dos bibliotecas. PuppeteerSharpusa PdfOptions con Format, Landscape y MarginOptions que contienen valores de cadena ("20mm").IronPDFutiliza propiedades RenderingOptions con enumeraciones directas de tamaño de papel, enumeraciones de orientación y valores de márgenes numéricos en milímetros.

Asignaciones clave:

  • Format = PaperFormat.A4PaperSize = PdfPaperSize.A4
  • Landscape = truePaperOrientation = PdfPaperOrientation.Landscape
  • MarginOptions.Top = "20mm"MarginTop = 20 (milímetros numéricos)

El problema de las fugas de memoria

PuppeteerSharp es notorio por la acumulación de memoria bajo carga sostenida:

// ❌ 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 elimina la necesidad de la infraestructura de agrupación de navegadores que requiere 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

Notas de migración críticas

Conversión de Async a Sync

PuppeteerSharp requiere async/await en todo momento;IronPDFadmite operaciones 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
$vbLabelText   $csharpLabel

Conversión de unidades de margen

PuppeteerSharp utiliza unidades de cadena;IronPDFutiliza milímetros numéricos:

// 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
$vbLabelText   $csharpLabel

Conversión de marcadores de posición de encabezado/pie

Clase PuppeteerSharp Marcador de posición IronPDF
<span class='pageNumber'> {page}
<span class='totalPages'> {total-pages}
<span class='date'> {date}
<span class='title'> {html-title}

Nuevas capacidades tras la migración

Después de migrar a IronPDF, obtendrá capacidades que PuppeteerSharpno puede proporcionar:

Fusión de 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

Marcas de agua

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

Protección con contraseña

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

Firmas digitales

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

Cumplimiento de PDF/A

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

Resumen comparativo de prestaciones

Métrica PuppeteerSharp IronPDF Mejora
Primer PDF (Cold Start) 45s+ ~20s 55%+ más rápido
PDF posteriores Variable Consistente Predecible
Uso de memoria 500MB+ (crece) ~50 MB (estable) 90% menos de memoria
Espacio en disco (Chromium) mÁS DE 300 MB 0 Eliminar descargas
Navegador Descargar Requerido No es necesario Cero configuración
Seguridad de los hilos Limitado Completo Concurrencia fiable
Tiempo de generación de PDF 45s 20s 55% más rápido

Conformidad FNMT-RCM, eIDAS y Crea y Crece: lo que PuppeteerSharp no puede ofrecer

Para los ISVs de software de gestión en España, la arquitectura de PuppeteerSharp resulta insuficiente en el contexto normativo actual. Un análisis de los requerimientos clave:

Ejemplo: factura VeriFactu con identificadores fiscales españoles en IronPDF

using IronPdf;

var renderer = new ChromePdfRenderer();
// Garantizar renderizado de fondos para leyenda VERI*FACTU
renderer.RenderingOptions.PrintHtmlBackgrounds = true;

var html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .cabecera { display: flex; justify-content: space-between; }
        .fiscal { font-size: 10px; color: #555; margin-top: 4px; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; -webkit-print-color-adjust: exact; }
    </style>
</head>
<body>
    <div class='cabecera'>
        <div>
            <strong>Acme Software S.L.</strong><br>
            <span class='fiscal'>NIF: B-98765432 | Inscrita en el Registro Mercantil de Madrid</span>
        </div>
        <div>
            <strong>FACTURA Nº 2026-0077</strong><br>
            <span class='fiscal'>Fecha: 28/05/2026</span>
        </div>
    </div>
    <table>
        <tr><th>Concepto</th><th>Base Imponible</th><th>IVA 21%</th><th>Total</th></tr>
        <tr><td>Servicio SaaS — mayo 2026</td><td>1.500,00 €</td><td>315,00 €</td><td>1.815,00 €</td></tr>
    </table>
    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT: sede.agenciatributaria.gob.es]
    </div>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
// Firma PAdES con certificado FNMT-RCM — no posible en PuppeteerSharp
// pdf.Sign(new PdfSignature("fnmt-rcm.pfx", "password"));

// TicketBAI XAdES si el cliente opera en Bizkaia, Gipuzkoa o Araba
// pdf.Sign(ticketBaiSignature);
pdf.SaveAs("factura-verifactu-2026-0077.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();
// Garantizar renderizado de fondos para leyenda VERI*FACTU
renderer.RenderingOptions.PrintHtmlBackgrounds = true;

var html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .cabecera { display: flex; justify-content: space-between; }
        .fiscal { font-size: 10px; color: #555; margin-top: 4px; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; -webkit-print-color-adjust: exact; }
    </style>
</head>
<body>
    <div class='cabecera'>
        <div>
            <strong>Acme Software S.L.</strong><br>
            <span class='fiscal'>NIF: B-98765432 | Inscrita en el Registro Mercantil de Madrid</span>
        </div>
        <div>
            <strong>FACTURA Nº 2026-0077</strong><br>
            <span class='fiscal'>Fecha: 28/05/2026</span>
        </div>
    </div>
    <table>
        <tr><th>Concepto</th><th>Base Imponible</th><th>IVA 21%</th><th>Total</th></tr>
        <tr><td>Servicio SaaS — mayo 2026</td><td>1.500,00 €</td><td>315,00 €</td><td>1.815,00 €</td></tr>
    </table>
    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT: sede.agenciatributaria.gob.es]
    </div>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
// Firma PAdES con certificado FNMT-RCM — no posible en PuppeteerSharp
// pdf.Sign(new PdfSignature("fnmt-rcm.pfx", "password"));

// TicketBAI XAdES si el cliente opera en Bizkaia, Gipuzkoa o Araba
// pdf.Sign(ticketBaiSignature);
pdf.SaveAs("factura-verifactu-2026-0077.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()
' Garantizar renderizado de fondos para leyenda VERI*FACTU
renderer.RenderingOptions.PrintHtmlBackgrounds = True

Dim html As String = "
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .cabecera { display: flex; justify-content: space-between; }
        .fiscal { font-size: 10px; color: #555; margin-top: 4px; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; -webkit-print-color-adjust: exact; }
    </style>
</head>
<body>
    <div class='cabecera'>
        <div>
            <strong>Acme Software S.L.</strong><br>
            <span class='fiscal'>NIF: B-98765432 | Inscrita en el Registro Mercantil de Madrid</span>
        </div>
        <div>
            <strong>FACTURA Nº 2026-0077</strong><br>
            <span class='fiscal'>Fecha: 28/05/2026</span>
        </div>
    </div>
    <table>
        <tr><th>Concepto</th><th>Base Imponible</th><th>IVA 21%</th><th>Total</th></tr>
        <tr><td>Servicio SaaS — mayo 2026</td><td>1.500,00 €</td><td>315,00 €</td><td>1.815,00 €</td></tr>
    </table>
    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT: sede.agenciatributaria.gob.es]
    </div>
</body>
</html>"

Dim pdf = renderer.RenderHtmlAsPdf(html)
' Firma PAdES con certificado FNMT-RCM — no posible en PuppeteerSharp
' pdf.Sign(New PdfSignature("fnmt-rcm.pfx", "password"))

' TicketBAI XAdES si el cliente opera en Bizkaia, Gipuzkoa o Araba
' pdf.Sign(ticketBaiSignature)
pdf.SaveAs("factura-verifactu-2026-0077.pdf")
$vbLabelText   $csharpLabel

Resumen de conformidad regulatoria

Requisito España PuppeteerSharp IronPDF
VERI*FACTU leyenda garantizada Riesgo (print-to-PDF omite fondos)
QR AEAT verificación Riesgo
Firma XAdES TicketBAI No
Firma PAdES FNMT-RCM (eIDAS) No
PDF/A para Facturae FACe No
LOPDGDD integridad bajo carga Riesgo (fugas memoria)
Crea y Crece B2B e-factura No (sin PDF/A) Preparado
Sin descarga Chromium (300 MB) No Sí (motor incluido)

Lista de comprobación de la migración

Pre-Migración

  • Identificar todos los usos de PuppeteerSharp en el código base
  • Valores de márgenes del documento (convertir cadenas a milímetros)
  • Nota sobre la sintaxis de marcador de posición de encabezado/pie de página para la conversión
  • Eliminar la infraestructura de agrupación/reciclaje del navegador
  • Obtenga la clave de licencia deIronPDFen IronPDF

Cambios en el paquete

  • Eliminar el paquete NuGet PuppeteerSharp
  • Eliminar la carpeta .local-chromium para recuperar ~300 MB de espacio en disco
  • Instalar IronPdf el paquete NuGet : dotnet add package IronPdf

Cambios de código

  • Actualizar las importaciones de espacios de nombres
  • Eliminar llamadas BrowserFetcher.DownloadAsync()
  • Eliminar Puppeteer.LaunchAsync() y la administración del navegador
  • Reemplace page.SetContentAsync() + page.PdfAsync() con RenderHtmlAsPdf()
  • Reemplace page.GoToAsync() + page.PdfAsync() con RenderUrlAsPdf()
  • Convertir cadenas de margen a valores milimétricos
  • Convertir la sintaxis de marcador de posición de encabezado/pie de página
  • Eliminar todo el código de eliminación de páginas/navegadores
  • Eliminar la infraestructura de agrupación de navegadores
  • Agregar inicialización de licencia al iniciar la aplicación

Posmigración

  • Comparación visual de la salida PDF
  • Prueba de carga para la estabilidad de la memoria (debe permanecer estable sin reciclar)
  • Verificar la representación del encabezado/pie de página con números de página
  • Agregue nuevas capacidades (seguridad, marcas de agua, fusión) según sea necesario

Contexto regulatorio español: automatización de navegador frente a generación estructurada VeriFactu

Para los ISVs españoles, PuppeteerSharp presenta limitaciones regulatorias específicas en flujos de facturación electrónica VeriFactu que IronPDF resuelve.

Por qué PuppeteerSharp no es apto para VeriFactu

El régimen VeriFactu (Real Decreto-Ley 15/2025) requiere:

  1. Salida print-to-PDF predecible: PuppeteerSharp genera un PDF equivalente a "Ctrl+P" del navegador, donde el fondo y los márgenes pueden omitirse por defecto. La leyenda VERI*FACTU y el QR de la AEAT requieren renderizado exacto con fondos y bordes.
  2. Firma TicketBAI XAdES: La firma digital XAdES para TicketBAI (Bizkaia, Gipuzkoa, Araba) requiere firma PDF nativa. PuppeteerSharp no soporta firmas digitales PDF.
  3. PDF/A para Facturae: La generación de Facturae XML con PDF adjunto conforme requiere PDF/A. PuppeteerSharp no soporta PDF/A.
  4. Gestión de memoria: Las fugas de memoria conocidas de PuppeteerSharp bajo carga comprometen la estabilidad de servidores de facturación que procesan altos volúmenes.

Generación de factura VeriFactu con IronPDF (salida estructurada, no print-to-PDF)

using IronPdf;

var renderer = new ChromePdfRenderer();
// Asegura renderizado de fondos y bordes para leyenda VERI*FACTU
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;

var html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .factura-header { display: flex; justify-content: space-between; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; -webkit-print-color-adjust: exact; }
    </style>
</head>
<body>
    <div class='factura-header'>
        <strong>FACTURA Nº 2026-0001</strong>
        <span>Fecha: 20/05/2026</span>
    </div>
    <table>
        <tr><th>Concepto</th><th>Total</th></tr>
        <tr><td>Licencia software .NET</td><td>1.210,00 €</td></tr>
    </table>

    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT]
    </div>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
// Firma TicketBAI XAdES — no disponible en PuppeteerSharp
// pdf.Sign(new PdfSignature("ticketbai.pfx", "password"));
pdf.SaveAs("factura-verifactu-2026-0001.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();
// Asegura renderizado de fondos y bordes para leyenda VERI*FACTU
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;

var html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .factura-header { display: flex; justify-content: space-between; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; -webkit-print-color-adjust: exact; }
    </style>
</head>
<body>
    <div class='factura-header'>
        <strong>FACTURA Nº 2026-0001</strong>
        <span>Fecha: 20/05/2026</span>
    </div>
    <table>
        <tr><th>Concepto</th><th>Total</th></tr>
        <tr><td>Licencia software .NET</td><td>1.210,00 €</td></tr>
    </table>

    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT]
    </div>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
// Firma TicketBAI XAdES — no disponible en PuppeteerSharp
// pdf.Sign(new PdfSignature("ticketbai.pfx", "password"));
pdf.SaveAs("factura-verifactu-2026-0001.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()
' Asegura renderizado de fondos y bordes para leyenda VERI*FACTU
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print

Dim html As String = "
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .factura-header { display: flex; justify-content: space-between; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; -webkit-print-color-adjust: exact; }
    </style>
</head>
<body>
    <div class='factura-header'>
        <strong>FACTURA Nº 2026-0001</strong>
        <span>Fecha: 20/05/2026</span>
    </div>
    <table>
        <tr><th>Concepto</th><th>Total</th></tr>
        <tr><td>Licencia software .NET</td><td>1.210,00 €</td></tr>
    </table>

    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT]
    </div>
</body>
</html>"

Dim pdf = renderer.RenderHtmlAsPdf(html)
' Firma TicketBAI XAdES — no disponible en PuppeteerSharp
' pdf.Sign(New PdfSignature("ticketbai.pfx", "password"))
pdf.SaveAs("factura-verifactu-2026-0001.pdf")
$vbLabelText   $csharpLabel

Lista de comprobación de conformidad VeriFactu post-migración

  • [ ] Eliminar PuppeteerSharp y la descarga de Chromium (~300 MB)
  • [ ] Implementar leyenda VERI*FACTU con fondo y borde garantizados
  • [ ] Añadir QR de la AEAT con URL de verificación
  • [ ] Configurar firma TicketBAI XAdES (no disponible en PuppeteerSharp)
  • [ ] Implementar Facturae XML con PDF/A adjunto si aplica
  • [ ] Verificar estabilidad de memoria bajo carga de facturación

Preguntas Frecuentes

¿Por qué el output print-to-PDF de PuppeteerSharp no es apto para VeriFactu?

PuppeteerSharp genera PDFs equivalentes a Ctrl+P en el navegador, donde los fondos y bordes se omiten por defecto. La leyenda VERI*FACTU y el QR de la AEAT requieren renderizado exacto con fondos y bordes visibles. El Real Decreto-Ley 15/2025 exige que estos elementos aparezcan correctamente. IronPDF garantiza el renderizado completo.

¿Las fugas de memoria de PuppeteerSharp son un problema de cumplimiento LOPDGDD?

Sí. La LOPDGDD, supervisada por la AEPD, exige que los sistemas de tratamiento de datos personales —incluyendo datos de facturas— implementen medidas técnicas adecuadas de disponibilidad e integridad. Las fugas de memoria que requieren reciclaje manual comprometen la disponibilidad del sistema de facturación.

¿Soporta IronPDF la firma XAdES para TicketBAI en Bizkaia, Gipuzkoa y Araba?

Sí. IronPDF incluye soporte nativo de firmas XAdES y PAdES, necesarias para TicketBAI en los tres territorios históricos vascos. PuppeteerSharp no tiene ninguna capacidad de firma digital PDF.

¿Cuánta memoria ahorra migrar de PuppeteerSharp a IronPDF?

PuppeteerSharp bajo carga sostenida puede consumir más de 500 MB con fugas acumulativas, requiriendo reciclaje manual del navegador. IronPDF mantiene un uso estable de aproximadamente 50 MB sin necesidad de reciclaje, con gestión automática de memoria. Esto es crítico para servidores de facturación de alto volumen.

¿Puede IronPDF generar PDF/A para Facturae XML en la plataforma FACe?

Sí. IronPDF soporta PDF/A-3 con Facturae XML embebido, cubriendo los requisitos de FACe para factura electrónica B2B bajo la Ley Crea y Crece. PuppeteerSharp no soporta el formato PDF/A.

Curtis Chau
Escritor Técnico

Curtis Chau tiene una licenciatura en Ciencias de la Computación (Carleton University) y se especializa en el desarrollo front-end con experiencia en Node.js, TypeScript, JavaScript y React. Apasionado por crear interfaces de usuario intuitivas y estéticamente agradables, disfruta trabajando con frameworks modernos y creando manuales bien ...

Leer más

Equipo de soporte de Iron

Estamos disponibles online las 24 horas, 5 días a la semana.
Chat
Email
Llámame