
IronPDF vs EvoPdf: ¿Qué Biblioteca PDF de .NET Ofrece Mejor Valor en 2026?
Cuando se construyen aplicaciones modernas de .NET que requieren funcionalidad PDF, elegir la biblioteca adecuada puede impactar significativamente en la velocidad de desarrollo, el rendimiento de la aplicación y los costos de mantenimiento a largo plazo. IronPDF y EvoPdf representan dos enfoques distintos para la generación y manipulación de PDF en el ecosistema .NET, cada uno con fortalezas únicas que se adaptan a diferentes escenarios de desarrollo.
Esta comparación examina ambas bibliotecas en dimensiones críticas, incluyendo la precisión de renderizado, el diseño de la API, consideraciones de rendimiento, compatibilidad de plataforma y costo total de propiedad. Ya sea que estés construyendo un sistema de procesamiento de documentos de alto volumen, firmando documentos o simplemente convirtiendo informes HTML a PDF, entender estas diferencias te ayudará a tomar una decisión informada que se alinee con tus requisitos técnicos y restricciones presupuestarias.
¿Cómo se Comparan IronPDF y EvoPdf a Simple Vista?
Antes de profundizar en comparaciones detalladas, aquí hay una visión general de cómo estas bibliotecas se comparan en categorías clave que más importan a los desarrolladores de .NET:
| Categoría | Característica/Aspecto | IronPDF | EvoPdf | Ventaja Clave |
|---|---|---|---|---|
| Arquitectura Principal | Filosofía de Diseño | Primero la simplicidad, APIs intuitivas | Control granular sobre configuraciones de conversión | Depende de la preferencia del equipo |
| Complejidad de la API | Métodos simples como RenderHtmlAsPdf() | Clase Converter con métodos como ConvertHtml() | Ambos: Conversión de una sola llamada | |
| Soporte de Plataforma | Multiplataforma | Windows, Linux, macOS a través de paquetes NuGet específicos de la plataforma | EvoPdf Next: Windows, Linux, macOS a través de paquetes NuGet por plataforma; EvoPdf Classic: Windows, más un cliente multiplataforma que llama a un EVO PDF Server alojado por separado | Ambos: Renderizado local multiplataforma (EvoPdf Next) |
| Versiones de .NET | .NET 10, 9, 8, 7, 6, 5, Core 3.1+, Standard 2.0, Framework 4.6.2+ | Next: .NET 10, 9, 8, 7, 6, Standard 2.0, Framework 4.6.2+; Classic: Framework 2.0+ | Ambos: Soporte de framework moderno | |
| Sistemas Operativos | Windows, Linux, macOS, Docker, Azure, AWS | Windows, Linux, macOS, Docker, Azure (EvoPdf Next) | Ambos: Soporte para Docker y la nube | |
| HTML a PDF | Motor de Renderizado | Chromium (CEF 109 en el paquete estándar; CEF 131 en IronPdf.UpdatedChrome) | Chromium 142 (EvoPdf Next); motor propio de EVO (EvoPdf Classic) | Ambos: Basado en Chromium |
| Soporte CSS3/HTML5 | Depende de la versión de Chromium incluida: en Windows, 109 en el paquete estándar y 131 en IronPdf.UpdatedChrome (por ejemplo, Tailwind CSS v4 necesita Chrome 111 o posterior) | Next: flexbox, grid, ES2015+, fuentes web | Ambos: Depende de la versión del motor | |
| Ejecución de JavaScript | Soporte de JavaScript con retraso de renderizado | Soporte de JavaScript con retraso de conversión | Ambos: Contenido dinámico | |
| Seguridad y Encriptación | Niveles de Encriptación | RC4-128, AES-128, AES-256 | RC4-40, RC4-128, AES-128, AES-256 | Ambos: AES-256 disponible |
| Opciones de Permiso | Controles de permiso granulares | Permisos granulares (imprimir, copiar, editar, anotar, rellenar formularios, ensamblar) | Ambos: Control granular | |
| Firmas Digitales | Firmas visuales integradas | Firmas visibles con soporte de imagen y marca de tiempo | Ambos: Firmas visuales | |
| Manipulación de Contenido | Método de Redacción | Eliminación verdadera de contenido, API de una línea | No se documenta función de redacción | IronPDF: Redacción incorporada |
| Marca de Agua | Basado en HTML/CSS, estilo completo | Plantillas HTML para marcas de agua y sellos | Ambos: Basado en HTML | |
| Sellado | Clases de sellador unificadas | Sellos HTML a través de plantillas | IronPDF: Clases de sellador dedicadas | |
| Conversiones de Archivos | DOCX a PDF | Incorporado DocxToPdfRenderer | Incluido en EVO PDF Toolkit (desde $650), no en la licencia HTML a PDF | IronPDF: Incluido en la licencia base |
| Experiencia del Desarrollador | Ejemplos de Código | Más de 100 ejemplos listos para ejecutar | Ejemplos de código en GitHub, demostración en línea | IronPDF: Recursos extensos |
| Documentación | Tutoriales, guías, videos, referencia de API | Documentación, referencia de API, FAQ de soporte | IronPDF: Múltiples caminos de aprendizaje | |
| Rendimiento | Concurrencia | Métodos de renderizado asíncronos | Métodos asíncronos (EvoPdf Next); renderizador persistente para conversiones paralelas | Ambos: Cargas de trabajo concurrentes |
| Licencias y Precios | Nivel de Entrada | Lite: $999 (1 desarrollador, 1 proyecto) | Despliegue: $450 (1 aplicación en 1 servidor, desarrolladores ilimitados, sin redistribución) | EvoPdf: Menor costo inicial |
| Licencia de Equipo | Plus: $1,499 (3 desarrolladores, 3 proyectos) | Ningún nivel cuenta desarrolladores; Empresa: $1,200 (aplicaciones y servidores ilimitados) | EvoPdf: El precio no depende del tamaño del equipo | |
| Redistribución | +$1,999 sin regalías (OEM/SaaS); una API pública que expone IronPDF necesita una licencia SDK | Solo Licencia de Empresa; no como servicio de conversión independiente o SDK | EvoPdf: Incluido en la Licencia de Empresa | |
| Opción de Suite | Iron Suite Lite: $2,998 (10 productos; 1 desarrollador, 1 ubicación, 1 proyecto) | EVO PDF Toolkit Empresa: $1,400 | Alcance diferente: Iron Suite agrega OCR, herramientas de código de barras y Office | |
| Soporte | Soporte Incluido | Sí: chat en vivo 24/5; soporte 24/7 con Soporte Premium (incluido durante la prueba) | Sí, primer año (estándar o prioritario, según licencia) | Ambos: Soporte incluido |
| Mejor Para | Casos de Uso | Aplicaciones web modernas, PDFs complejos, redacción | HTML, Word y Excel a PDF con licencia a nivel de empresa | Dependiente del contexto |
Nota. EvoPdf ofrece precios competitivos para equipos grandes. IronPDF incluye redacción incorporada y conversión de DOCX a PDF en su licencia base.
Comprendiendo IronPDF y EvoPdf: Fortalezas y Filosofía Principales
¿Qué Hace que IronPDF Destaque en el Mercado de Bibliotecas PDF para .NET?
IronPDF es una biblioteca PDF para .NET diseñada con la productividad del desarrollador en su núcleo. Construida sobre una base de simplicidad sin sacrificar poder, IronPDF permite a los desarrolladores de .NET crear, editar y manipular documentos PDF utilizando APIs intuitivas que reflejan patrones familiares de desarrollo web. La característica destacada de la biblioteca es su motor de renderizado basado en Chromium, que ejecuta JavaScript y carga fuentes web; cuánto CSS moderno maneja depende de la versión de Chromium que envíes. El paquete estándar IronPdf incluye Chromium 109 para compatibilidad con servidores Windows más antiguos; el paquete solo para Windows IronPdf.UpdatedChrome incluye Chromium 131 y maneja correctamente características CSS más nuevas como subgrid, pero no soporta procesos de 32 bits, Windows Server 2012 o modo SingleProcess, por lo que los dos paquetes no son intercambiables en cada destino.
La biblioteca está dirigida a aplicaciones que renderizan documentos HTML, manipulan PDFs existentes y protegen documentos con encriptación, firmas y redacción. Su extenso conjunto de características incluye no solo generación básica de PDF, sino capacidades avanzadas como firmas digitales, llenado de formularios, integración de OCR a través de IronOCR, y conversiones de formato de documentos como DOCX a PDF. La compatibilidad multiplataforma de IronPDF se extiende más allá del simple soporte de framework, funcionando en Windows, Linux, macOS, contenedores Docker y plataformas en la nube como Azure y AWS.
¿Cómo Aborda EvoPdf la Generación de PDF de Manera Diferente?
EvoPdf se centra en la conversión de HTML a PDF con un énfasis en la personalización y el control. La biblioteca proporciona a los desarrolladores un control granular sobre el proceso de conversión, permitiendo un ajuste fino de los parámetros de renderizado, los diseños de página y las configuraciones de conversión. EvoPdf se distribuye en dos ediciones: EvoPdf Next, que utiliza un motor de renderizado basado en Chromium (Chromium 142, según EVO PDF) y se ejecuta en Windows, Linux y macOS, y EvoPdf Classic, que utiliza el propio motor de renderizado de EVO y se ejecuta en Windows. El EVO PDF Toolkit agrega conversión de Word, Excel, RTF y Markdown a PDF, así como componentes de procesamiento de PDF.
Una fortaleza notable de EvoPdf es su licencia: ningún nivel de licencia cuenta desarrolladores, y la licencia de Empresa cubre aplicaciones y servidores ilimitados e incluye redistribución dentro de tus propias aplicaciones. Para cargas de trabajo de servidor de alto volumen, EvoPdf Next documenta un modo de renderizador persistente que mantiene el motor de renderizado en funcionamiento entre conversiones. La biblioteca también soporta escenarios de ASP.NET como la conversión de páginas que requieren cookies de autenticación.
¿Cómo se Comparan las Capacidades Multiplataforma entre Bibliotecas?
Arquitectura Multiplataforma Moderna de IronPDF
IronPDF se ejecuta en varias versiones de .NET, sistemas operativos y plataformas en la nube:
- Soporte de Versión de .NET:
- .NET 10, 9, 8, 7, 6, 5, y Core 3.1+
- .NET Standard 2.0+
- .NET Framework 4.6.2+
- Soporte completo para C#, VB.NET y F#
- Compatibilidad con Sistemas Operativos:
- Windows (x64; x86 solo con el paquete estándar, ya que IronPdf.UpdatedChrome no soporta procesos de 32 bits)
- Linux (Ubuntu, Debian, CentOS; Alpine a través del contenedor IronPdfEngine)
- macOS (Intel y Apple Silicon)
- Contenedores Docker con imágenes preconfiguradas
- Integración con Plataformas en la Nube:
- Azure App Service, Functions y VMs
- AWS Lambda y EC2
- Despliegues en Kubernetes
IronPDF envía sus binarios de Chromium en paquetes NuGet específicos de la plataforma (IronPdf para Windows, IronPdf.Linux, IronPdf.MacOs y IronPdf.MacOs.ARM). En Linux, IronPDF intenta instalar dependencias del sistema faltantes automáticamente por defecto; esto requiere derechos de sudo, y de lo contrario, las dependencias se instalan manualmente. Esto mantiene los pasos de despliegue cortos para la mayoría de los entornos.
Soporte de Plataforma de EvoPdf
EvoPdf soporta un rango similar de versiones de .NET, con soporte de plataforma que depende de la edición:
- Soporte de Framework de .NET:
- EvoPdf Next: .NET 10, 9, 8, 7 y 6, .NET Standard 2.0, .NET Framework 4.6.2 a 4.8.1
- EvoPdf Classic: .NET 10 a 6, .NET Standard 2.0, .NET Framework 2.0 y posteriores
- Consideraciones de Plataforma:
- EvoPdf Next: Windows (x64, ARM64), Linux (x64, ARM64) y macOS (ARM64), con un paquete NuGet por plataforma
- EvoPdf Next se ejecuta en Azure App Service, Azure Functions y Docker; el motor de renderizado se aloja en el proceso de la aplicación, sin navegador para instalar
- EvoPdf Classic: renderiza localmente solo en Windows
- Cliente EvoPdf Classic: se ejecuta en Windows, Linux y macOS y envía conversiones a un EVO PDF Server instalado por separado (instalado como un servicio en la nube de Azure, aplicación IIS o servicio de Windows)
EvoPdf Next proporciona renderizado local nativo en Windows, Linux y macOS. Una aplicación construida en EvoPdf Classic que necesita ejecutarse en Linux o macOS puede moverse a EvoPdf Next, para lo cual EVO PDF publica una guía de migración de Classic a Next, o mantener el renderizado Classic en un EVO PDF Server separado y llamarlo a través de la biblioteca cliente.
¿Qué Biblioteca Ofrece Mejor Funcionalidad PDF para Tareas Comunes?
Cada ejemplo de código en este artículo es un programa de consola .NET 8 completo: crea un proyecto con dotnet new console, agrega el paquete NuGet nombrado en el primer comentario del ejemplo y reemplaza Program.cs con el ejemplo. Los ejemplos declaran sus propias directivas using, por lo que se compilan con o sin usings implícitos. Fueron compilados y ejecutados contra IronPdf 2026.9.2, EvoPdf.HtmlToPdf 14.0.2 y EvoPdf.PdfSecurity 14.0.2. IronPDF necesita una clave de licencia, como una clave de prueba gratuita, establecida a través de IronPdf.License.LicenseKey o una entrada IronPdf.LicenseKey en appsettings.json. EvoPdf se ejecuta sin una clave y agrega una marca de agua de evaluación a la salida.
Conversión de HTML a PDF: Calidad de Renderizado y Rendimiento
La característica más fundamental de ambas bibliotecas es la conversión de HTML a PDF, y sus APIs adoptan diferentes enfoques.
Ejemplo de HTML a PDF de IronPDF
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;
using IronPdf.Rendering;
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
EnableJavaScript = true,
// Page margins in millimetres
MarginTop = 20,
MarginBottom = 20,
MarginLeft = 15,
MarginRight = 15,
CssMediaType = PdfCssMediaType.Print,
ViewPortWidth = 1920,
FitToPaperMode = FitToPaperModes.Automatic
}
};
// Render only after the page calls window.ironpdf.notifyRender(), or after 10 seconds at most
renderer.RenderingOptions.WaitFor.JavaScript(10000);
// The page loads Chart.js and a Google Font from their CDNs, so the renderer needs network access
var htmlContent = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap' rel='stylesheet'>
<style>
body { font-family: 'Roboto', sans-serif; }
.chart-container { width: 100%; height: 400px; }
@media print {
.no-print { display: none; }
}
</style>
<script src='https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js'></script>
</head>
<body>
<h1>Dynamic Sales Report</h1>
<div class='chart-container'>
<canvas id='salesChart'></canvas>
</div>
<script>
new Chart(document.getElementById('salesChart'), {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'Sales 2025',
data: [65, 78, 90, 81, 96],
borderColor: 'rgb(75, 192, 192)',
tension: 0.4
}]
},
// No animation, so the chart is fully drawn when the constructor returns
options: { animation: false }
});
window.ironpdf.notifyRender();
</script>
</body>
</html>";
using var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("sales-report.pdf");' NuGet: Install-Package IronPdf
Imports IronPdf
Imports IronPdf.Engines.Chrome
Imports IronPdf.Rendering
Dim renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.EnableJavaScript = True,
' Page margins in millimetres
.MarginTop = 20,
.MarginBottom = 20,
.MarginLeft = 15,
.MarginRight = 15,
.CssMediaType = PdfCssMediaType.Print,
.ViewPortWidth = 1920,
.FitToPaperMode = FitToPaperModes.Automatic
}
}
' Render only after the page calls window.ironpdf.notifyRender(), or after 10 seconds at most
renderer.RenderingOptions.WaitFor.JavaScript(10000)
' The page loads Chart.js and a Google Font from their CDNs, so the renderer needs network access
Dim htmlContent = "
<!DOCTYPE html>
<html>
<head>
<link href='https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap' rel='stylesheet'>
<style>
body { font-family: 'Roboto', sans-serif; }
.chart-container { width: 100%; height: 400px; }
@media print {
.no-print { display: none; }
}
</style>
<script src='https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js'></script>
</head>
<body>
<h1>Dynamic Sales Report</h1>
<div class='chart-container'>
<canvas id='salesChart'></canvas>
</div>
<script>
new Chart(document.getElementById('salesChart'), {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'Sales 2025',
data: [65, 78, 90, 81, 96],
borderColor: 'rgb(75, 192, 192)',
tension: 0.4
}]
},
options: { animation: false }
});
window.ironpdf.notifyRender();
</script>
</body>
</html>"
Using pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("sales-report.pdf")
End UsingEste ejemplo de IronPDF muestra:
- Ejecución de JavaScript: El JavaScript de la página (aquí Chart.js) se ejecuta antes de renderizar
- Señal de Renderizado Explícita:
WaitFor.JavaScript()espera a que la página llame awindow.ironpdf.notifyRender()en lugar de adivinar con un retraso fijo - Fuentes Web: Las fuentes referenciadas por la página se cargan y se incrustan
- Consultas de Medios de Impresión:
CssMediaType.Printaplica las reglas@media printde la página
Ejemplo de HTML a PDF de EvoPdf
// NuGet: Install-Package EvoPdf.HtmlToPdf (EvoPdf Classic, Windows)
using System.IO;
using EvoPdf;
HtmlToPdfConverter converter = new HtmlToPdfConverter();
// Production use needs a license key. Leave this line out to evaluate:
// the output then carries an evaluation watermark. An invalid key makes the conversion throw.
// converter.LicenseKey = "<your EvoPdf license key>";
converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
converter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
// EvoPdf margins are in points (1/72 inch): 57 pt is about 20 mm, 43 pt about 15 mm,
// matching the IronPDF example above, whose margins are in millimetres
converter.PdfDocumentOptions.TopMargin = 57;
converter.PdfDocumentOptions.BottomMargin = 57;
converter.PdfDocumentOptions.LeftMargin = 43;
converter.PdfDocumentOptions.RightMargin = 43;
converter.JavaScriptEnabled = true;
converter.ConversionDelay = 2; // seconds
// For pages behind HTTP authentication, also set
// converter.AuthenticationOptions.Username and .Password
// Convert HTML string
string htmlString = @"
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; }
</style>
</head>
<body>
<h1>Invoice</h1>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
<tr>
<td>Product A</td>
<td>5</td>
<td>$50.00</td>
</tr>
</table>
</body>
</html>";
// Perform conversion
byte[] pdfBytes = converter.ConvertHtml(htmlString, "");
// Save to file
File.WriteAllBytes("invoice.pdf", pdfBytes);' NuGet: Install-Package EvoPdf.HtmlToPdf (EvoPdf Classic, Windows)
Imports System.IO
Imports EvoPdf
Dim converter As New HtmlToPdfConverter()
' Production use needs a license key. Leave this line out to evaluate:
' the output then carries an evaluation watermark. An invalid key makes the conversion throw.
' converter.LicenseKey = "<your EvoPdf license key>"
converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4
converter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait
' EvoPdf margins are in points (1/72 inch): 57 pt is about 20 mm, 43 pt about 15 mm,
' matching the IronPDF example above, whose margins are in millimetres
converter.PdfDocumentOptions.TopMargin = 57
converter.PdfDocumentOptions.BottomMargin = 57
converter.PdfDocumentOptions.LeftMargin = 43
converter.PdfDocumentOptions.RightMargin = 43
converter.JavaScriptEnabled = True
converter.ConversionDelay = 2 ' seconds
' For pages behind HTTP authentication, also set
' converter.AuthenticationOptions.Username and .Password
' Convert HTML string
Dim htmlString As String = "
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; }
</style>
</head>
<body>
<h1>Invoice</h1>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
<tr>
<td>Product A</td>
<td>5</td>
<td>$50.00</td>
</tr>
</table>
</body>
</html>"
' Perform conversion
Dim pdfBytes() As Byte = converter.ConvertHtml(htmlString, "")
' Save to file
File.WriteAllBytes("invoice.pdf", pdfBytes)El convertidor de EvoPdf sigue un patrón de configurar y luego convertir: establece PdfDocumentOptions, luego llama a ConvertHtml() o ConvertUrl(). Cada ejemplo de EvoPdf en este artículo utiliza la API de EvoPdf Classic (paquete EvoPdf.HtmlToPdf), que renderiza en Windows. EvoPdf Next, la edición basada en Chromium, es un conjunto separado de paquetes NuGet con su propia API: por ejemplo, su clave de licencia se establece una vez por proceso en la propiedad estática Licensing.LicenseKey. EVO documenta soporte en Next para flexbox, grid, JavaScript ES2015+ y fuentes web.
Seguridad y Encriptación de PDF: Protegiendo Documentos Sensibles
La seguridad es primordial al tratar con documentos sensibles. Ambas bibliotecas ofrecen protección con contraseña, controles de permiso y encriptación.
Implementación de Seguridad Avanzada de IronPDF
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Editing;
using IronPdf.Security;
using IronPdf.Signing;
using IronSoftware.Drawing;
using var pdf = PdfDocument.FromFile("confidential-report.pdf");
// Finish every content change before signing
pdf.ApplyWatermark("<h2 style='color:red; opacity:0.5;'>CONFIDENTIAL</h2>",
45, VerticalAlignment.Middle, HorizontalAlignment.Center);
// Descriptive document properties (these do not restrict access)
pdf.MetaData.Author = "Finance Team";
pdf.MetaData.Title = "Quarterly Report (Internal)";
pdf.MetaData.ModifiedDate = DateTime.UtcNow;
// Owner password: required to change the permissions below
pdf.SecuritySettings.OwnerPassword = "owner-password";
// User password: required to open the document
pdf.SecuritySettings.UserPassword = "user-password";
pdf.SecuritySettings.AllowUserCopyPasteContentForAccessibility = false;
pdf.SecuritySettings.AllowUserAnnotations = false;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserFormData = true;
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.PrintLowQuality;
pdf.SecuritySettings.EncryptionType = PdfEncryptionType.Aes_256;
// Visible digital signature: image file, page index, and position/size on the page
var signature = new PdfSignature("certificate.pfx", "cert-password")
{
SigningReason = "Document Approval",
SigningLocation = "Head Office",
SigningContact = "security@example.com",
SignatureImage = new PdfSignatureImage("signature.png", 0, new Rectangle(100, 100, 200, 50))
};
pdf.Sign(signature);
// The signature is applied when the file is saved
pdf.SaveAs("secured-document.pdf");' NuGet: Install-Package IronPdf
Imports System
Imports IronPdf
Imports IronPdf.Editing
Imports IronPdf.Security
Imports IronPdf.Signing
Imports IronSoftware.Drawing
Dim pdf = PdfDocument.FromFile("confidential-report.pdf")
' Finish every content change before signing
pdf.ApplyWatermark("<h2 style='color:red; opacity:0.5;'>CONFIDENTIAL</h2>", 45, VerticalAlignment.Middle, HorizontalAlignment.Center)
' Descriptive document properties (these do not restrict access)
pdf.MetaData.Author = "Finance Team"
pdf.MetaData.Title = "Quarterly Report (Internal)"
pdf.MetaData.ModifiedDate = DateTime.UtcNow
' Owner password: required to change the permissions below
pdf.SecuritySettings.OwnerPassword = "owner-password"
' User password: required to open the document
pdf.SecuritySettings.UserPassword = "user-password"
pdf.SecuritySettings.AllowUserCopyPasteContentForAccessibility = False
pdf.SecuritySettings.AllowUserAnnotations = False
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserFormData = True
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.PrintLowQuality
pdf.SecuritySettings.EncryptionType = PdfEncryptionType.Aes_256
' Visible digital signature: image file, page index, and position/size on the page
Dim signature = New PdfSignature("certificate.pfx", "cert-password") With {
.SigningReason = "Document Approval",
.SigningLocation = "Head Office",
.SigningContact = "security@example.com",
.SignatureImage = New PdfSignatureImage("signature.png", 0, New Rectangle(100, 100, 200, 50))
}
pdf.Sign(signature)
' The signature is applied when the file is saved
pdf.SaveAs("secured-document.pdf")Las características de seguridad de IronPDF mostradas aquí:
- Permisos Granulares: Control de calidad de impresión, copia, anotaciones, llenado de formularios y ediciones
- Firmas Digitales Visibles: Una firma con una razón, ubicación e imagen de firma
- Propiedades del Documento: Establecer autor, título y fechas (solo descriptivo)
- Protección en Capas: Combina una marca de agua, encriptación y una firma en un documento
Configuración de Seguridad de EvoPdf
// NuGet: Install-Package EvoPdf.PdfSecurity
// (licensed with the EVO PDF Toolkit; not included in the standalone HTML to PDF license)
using EvoPdf.PdfSecurity;
PdfSecurityOptions securityOptions = new PdfSecurityOptions();
// Set basic security parameters
securityOptions.UserPassword = "user123";
securityOptions.OwnerPassword = "owner456";
securityOptions.EncryptionAlgorithm = EncryptionAlgorithm.AES;
securityOptions.KeySize = EncryptionKeySize.EncryptKey256Bit;
// Configure permissions
securityOptions.CanPrint = true;
securityOptions.CanCopyContent = false;
securityOptions.CanEditContent = false;
securityOptions.CanEditAnnotations = false;
securityOptions.CanFillFormFields = true;
securityOptions.CanAssembleDocument = false;
// Apply security to existing PDF
PdfSecurityManager securityManager = new PdfSecurityManager(securityOptions);
securityManager.SaveSecuredPdfToFile("input.pdf", "secured-output.pdf");' NuGet: Install-Package EvoPdf.PdfSecurity
' (licensed with the EVO PDF Toolkit; not included in the standalone HTML to PDF license)
Imports EvoPdf.PdfSecurity
Dim securityOptions As New PdfSecurityOptions()
' Set basic security parameters
securityOptions.UserPassword = "user123"
securityOptions.OwnerPassword = "owner456"
securityOptions.EncryptionAlgorithm = EncryptionAlgorithm.AES
securityOptions.KeySize = EncryptionKeySize.EncryptKey256Bit
' Configure permissions
securityOptions.CanPrint = True
securityOptions.CanCopyContent = False
securityOptions.CanEditContent = False
securityOptions.CanEditAnnotations = False
securityOptions.CanFillFormFields = True
securityOptions.CanAssembleDocument = False
' Apply security to existing PDF
Dim securityManager As New PdfSecurityManager(securityOptions)
securityManager.SaveSecuredPdfToFile("input.pdf", "secured-output.pdf")EvoPdf cubre los mismos controles básicos: contraseñas de usuario y propietario, encriptación y permisos para impresión, copia, edición, anotaciones, llenado de formularios y ensamblaje de documentos. EVO documenta el algoritmo (RC4 o AES) y el tamaño de la clave (40, 128 o 256 bits) como configuraciones separadas; en nuestras pruebas con la versión 14.0.2, RC4 con claves de 40 o 128 bits y AES con claves de 128 o 256 bits produjeron la encriptación esperada, así que usa AES-128 o AES-256; RC4 es un algoritmo heredado. Con la licencia independiente de HTML a PDF, las propias PdfSecurityOptions del convertidor aplican la misma protección mientras se genera el PDF, sin el componente de Seguridad de PDF separado.
Redacción de Contenido: Eliminando Información Sensible
Eliminar permanentemente texto sensible antes de compartir un documento es un requisito común en aplicaciones que manejan datos personales. La redacción es un bloque de construcción para ese trabajo; por sí sola no hace que una aplicación cumpla con regulaciones como GDPR, HIPAA o CCPA.
Ejemplo de Redacción de IronPDF
// NuGet: Install-Package IronPdf
using IronPdf;
using IronSoftware.Drawing;
// This example expects a PDF with at least three pages
using var pdf = PdfDocument.FromFile("customer-records.pdf");
// 1. Redact a specific value on every page
pdf.RedactTextOnAllPages("123-45-6789");
// 2. Redact a word on specific pages (zero-based page indexes)
pdf.RedactTextOnPages(new[] { 0, 1, 2 }, "Confidential", CaseSensitive: false);
// 3. Redact a rectangular region on the first page
pdf.RedactRegionOnPage(0, new RectangleF(100, 200, 300, 50));
// 4. Replace a complete sensitive value with a label instead of drawing a black box
pdf.RedactTextOnAllPages("ACCT-0042-7781", DrawRectangles: false, ReplacementText: "[REDACTED]");
pdf.SaveAs("redacted-records.pdf");' NuGet: Install-Package IronPdf
Imports IronPdf
Imports IronSoftware.Drawing
' This example expects a PDF with at least three pages
Dim pdf = PdfDocument.FromFile("customer-records.pdf")
' 1. Redact a specific value on every page
pdf.RedactTextOnAllPages("123-45-6789")
' 2. Redact a word on specific pages (zero-based page indexes)
pdf.RedactTextOnPages(New Integer() {0, 1, 2}, "Confidential", CaseSensitive:=False)
' 3. Redact a rectangular region on the first page
pdf.RedactRegionOnPage(0, New RectangleF(100, 200, 300, 50))
' 4. Replace a complete sensitive value with a label instead of drawing a black box
pdf.RedactTextOnAllPages("ACCT-0042-7781", DrawRectangles:=False, ReplacementText:="[REDACTED]")
pdf.SaveAs("redacted-records.pdf")Las capacidades de redacción de IronPDF incluyen:
- Eliminación de Contenido: El texto coincidente se elimina del contenido de la página, por lo que ya no se puede extraer, no solo cubrir
- Opciones de Coincidencia: Coincidencia sensible a mayúsculas y minúsculas y de palabra completa
- Apariencia de Redacción: Dibujar cuadros negros o insertar texto de reemplazo
- Redacción Selectiva: Apuntar a páginas o regiones específicas
La redacción de texto coincide con el texto en el contenido de la página. El texto dentro de imágenes, como una página escaneada, no se coincide; una redacción de región cubre un área fija independientemente de lo que haya en ella. EvoPdf no documenta una función de redacción.
Manejo de Formularios: Creando PDFs Interactivos
Ambas bibliotecas soportan formularios PDF, pero con diferentes enfoques para la creación y manipulación.
Ejemplo de Formularios de IronPDF
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
// Create a new PDF with an HTML form
var html = @"
<html>
<body>
<h2>Employee Information Form</h2>
<form>
<label>Full Name:</label>
<input type='text' name='fullName' required />
<label>Email:</label>
<input type='email' name='email' required />
<label>Department:</label>
<select name='department'>
<option value=''>Select Department</option>
<option value='IT'>Information Technology</option>
<option value='HR'>Human Resources</option>
<option value='Sales'>Sales</option>
</select>
<label>Start Date:</label>
<input type='text' name='startDate' placeholder='YYYY-MM-DD' />
<label>
<input type='checkbox' name='agreement' />
I agree to the terms and conditions
</label>
<button type='submit'>Submit</button>
</form>
</body>
</html>";
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
CreatePdfFormsFromHtml = true // Enable form field creation
}
};
using var pdf = renderer.RenderHtmlAsPdf(html);
// Programmatically fill form fields
pdf.Form.FindFormField("fullName").Value = "John Doe";
pdf.Form.FindFormField("email").Value = "john.doe@example.com";
// A dropdown takes one of its displayed choices, not the HTML option value ("IT")
pdf.Form.FindFormField("department").Value = "Information Technology";
pdf.Form.FindFormField("startDate").Value = DateTime.Now.ToString("yyyy-MM-dd");
// "Yes" is the checkbox's checked state
pdf.Form.FindFormField("agreement").Value = "Yes";
// Make specific fields read-only
pdf.Form.FindFormField("email").ReadOnly = true;
// Save as fillable form
pdf.SaveAs("fillable-form.pdf");
// Or flatten the form (convert to static content)
pdf.Flatten();
pdf.SaveAs("completed-form.pdf");' NuGet: Install-Package IronPdf
Imports System
Imports IronPdf
' Create a new PDF with an HTML form
Dim html = "
<html>
<body>
<h2>Employee Information Form</h2>
<form>
<label>Full Name:</label>
<input type='text' name='fullName' required />
<label>Email:</label>
<input type='email' name='email' required />
<label>Department:</label>
<select name='department'>
<option value=''>Select Department</option>
<option value='IT'>Information Technology</option>
<option value='HR'>Human Resources</option>
<option value='Sales'>Sales</option>
</select>
<label>Start Date:</label>
<input type='text' name='startDate' placeholder='YYYY-MM-DD' />
<label>
<input type='checkbox' name='agreement' />
I agree to the terms and conditions
</label>
<button type='submit'>Submit</button>
</form>
</body>
</html>"
Dim renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.CreatePdfFormsFromHtml = True ' Enable form field creation
}
}
Using pdf = renderer.RenderHtmlAsPdf(html)
' Programmatically fill form fields
pdf.Form.FindFormField("fullName").Value = "John Doe"
pdf.Form.FindFormField("email").Value = "john.doe@example.com"
' A dropdown takes one of its displayed choices, not the HTML option value ("IT")
pdf.Form.FindFormField("department").Value = "Information Technology"
pdf.Form.FindFormField("startDate").Value = DateTime.Now.ToString("yyyy-MM-dd")
' "Yes" is the checkbox's checked state
pdf.Form.FindFormField("agreement").Value = "Yes"
' Make specific fields read-only
pdf.Form.FindFormField("email").ReadOnly = True
' Save as fillable form
pdf.SaveAs("fillable-form.pdf")
' Or flatten the form (convert to static content)
pdf.Flatten()
pdf.SaveAs("completed-form.pdf")
End UsingLas características de manejo de formularios de IronPDF:
- Generación Automática de Formularios: Convierte formularios HTML en formularios PDF
- Manipulación Programática: Rellenar, leer y modificar campos de formulario a través de la API
- Tipos de Campo: Las entradas de texto (incluyendo entradas de correo electrónico, número y teléfono) y áreas de texto se convierten en campos de texto; las casillas de verificación, botones de radio y menús desplegables mantienen su tipo. Las entradas de fecha HTML no se convierten en campos de formulario, por lo que la fecha de inicio arriba usa una entrada de texto.
- Propiedades de Campo: Establecer valores y banderas de solo lectura
- Aplanamiento de Formularios: Convertir formularios rellenados en PDFs estáticos
Consideraciones de Rendimiento
Las características de rendimiento varían significativamente según la complejidad del documento y el caso de uso:
Cronometrando un Lote de Documentos
// NuGet: Install-Package IronPdf
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using IronPdf;
// Timing harness for a batch of documents. Replace the generated HTML with your own templates.
const int documentCount = 100;
const int maxConcurrency = 4;
var htmlDocuments = Enumerable.Range(1, documentCount)
.Select(i => $"<html><body><h1>Invoice {i}</h1><p>Amount due: {i * 10} USD</p></body></html>")
.ToList();
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
EnableJavaScript = false // static content only
}
};
// Cap how many renders run at once instead of starting every render immediately
using var gate = new SemaphoreSlim(maxConcurrency);
var stopwatch = Stopwatch.StartNew();
var tasks = htmlDocuments.Select(async (html, index) =>
{
await gate.WaitAsync();
try
{
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
pdf.SaveAs($"invoice-{index + 1}.pdf");
}
finally
{
gate.Release();
}
});
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($"Documents: {documentCount}, at most {maxConcurrency} at a time");
Console.WriteLine($"Total elapsed: {stopwatch.ElapsedMilliseconds} ms");
// Elapsed time divided by the document count: an amortized figure, not the latency of one request
Console.WriteLine($"Amortized time per document: {stopwatch.ElapsedMilliseconds / (double)documentCount:F1} ms");
// Resident memory of this process only, sampled once at the end; the Chromium helper
// processes are not included, and this is not the peak
Console.WriteLine($"Working set of this process at end: {Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024} MB");' NuGet: Install-Package IronPdf
Imports System
Imports System.Diagnostics
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks
Imports IronPdf
' Timing harness for a batch of documents. Replace the generated HTML with your own templates.
Const documentCount As Integer = 100
Const maxConcurrency As Integer = 4
Dim htmlDocuments = Enumerable.Range(1, documentCount) _
.Select(Function(i) $"<html><body><h1>Invoice {i}</h1><p>Amount due: {i * 10} USD</p></body></html>") _
.ToList()
Dim renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.EnableJavaScript = False ' static content only
}
}
' Cap how many renders run at once instead of starting every render immediately
Using gate As New SemaphoreSlim(maxConcurrency)
Dim stopwatch = Stopwatch.StartNew()
Dim tasks = htmlDocuments.Select(Async Function(html, index)
Await gate.WaitAsync()
Try
Using pdf = Await renderer.RenderHtmlAsPdfAsync(html)
pdf.SaveAs($"invoice-{index + 1}.pdf")
End Using
Finally
gate.Release()
End Try
End Function)
Await Task.WhenAll(tasks)
stopwatch.Stop()
Console.WriteLine($"Documents: {documentCount}, at most {maxConcurrency} at a time")
Console.WriteLine($"Total elapsed: {stopwatch.ElapsedMilliseconds} ms")
' Elapsed time divided by the document count: an amortized figure, not the latency of one request
Console.WriteLine($"Amortized time per document: {stopwatch.ElapsedMilliseconds / CDbl(documentCount):F1} ms")
' Resident memory of this process only, sampled once at the end; the Chromium helper
' processes are not included, and this is not the peak
Console.WriteLine($"Working set of this process at end: {Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024} MB")
End UsingEste artículo no presenta un benchmark comparativo: los resultados dependen de plantillas, hardware y despliegue, así que mide con los tuyos. Palancas documentadas para cada biblioteca:
- Versión del motor de IronPDF: Para renders lentos de páginas modernas, pesadas en JavaScript o profundamente anidadas, incluidas páginas construidas en Bootstrap o Tailwind, IronPDF recomienda el paquete IronPdf.UpdatedChrome, que incluye Chromium 131 en lugar del Chromium 109 del paquete estándar
- Concurrencia de IronPDF: Métodos de renderizado asíncronos como
RenderHtmlAsPdfAsync, con tu propio límite en cuántos renders se ejecutan a la vez - Modos de renderizado de EvoPdf Next:
GlobalSettings.HtmlRendererModeconfigurado enPersistentProcess(el predeterminado) mantiene un proceso de motor de renderizado en funcionamiento entre conversiones, yProcessPerConversioninicia uno por conversión; las conversiones pueden ejecutarse en paralelo, cada una con su propio convertidor, yGlobalSettings.MaxParallelConversionslimita cuántas se ejecutan a la vez - Métodos asíncronos de EvoPdf Next:
ConvertHtmlAsyncyConvertUrlAsyncpara código async/await
¿Cómo se Comparan los Modelos de Precios para Diferentes Tamaños de Equipo?
Estructura de Licencias de IronPDF
IronPDF ofrece varias opciones de precios, incluidas licencias Lite, Plus y Professional, con la opción de redistribución sin regalías. El modelo de licencia está diseñado para escalar con las necesidades de tu equipo y proyecto (precios a septiembre de 2026):
- Licencia Lite: $999
- 1 desarrollador
- 1 ubicación
- 1 proyecto
- Soporte por correo electrónico
- Ideal para: Desarrolladores individuales, proyectos pequeños
- Licencia Plus: $1,499
- 3 desarrolladores
- 3 ubicaciones
- 3 proyectos
- Soporte por correo electrónico (SLA de 48 horas) y chat en vivo
- Ideal para: Equipos pequeños, múltiples proyectos
- Licencia Professional: $2,399
- 10 desarrolladores
- 10 ubicaciones
- 10 proyectos
- Soporte por correo electrónico (SLA de 24 horas), chat en vivo, teléfono y compartición de pantalla
- Ideal para: Equipos medianos a grandes
- Opciones Adicionales:
- Redistribución sin regalías (OEM/SaaS): +$1,999, para software comercial y SaaS donde los usuarios finales no llaman directamente a las APIs de IronPDF
- Licencia SDK: requerida cuando un producto expone la funcionalidad de IronPDF a otros desarrolladores a través de una API pública
- Extensiones de soporte y actualizaciones: 1, 3 o 5 años, con precio por nivel de licencia
- Iron Suite: los 10 productos de Iron Software, licenciados en los mismos niveles; Iron Suite Lite (1 desarrollador, 1 ubicación, 1 proyecto) es $2,998
Opciones de Licencia de EvoPdf
EVO PDF Toolkit y el convertidor HTML a PDF independiente ofrecen cada uno dos niveles de licencia, Despliegue y Empresa (precios a septiembre de 2026; verifica precios actuales en evopdf.com/buy). La licencia HTML a PDF cubre tanto los convertidores Next como Classic; los otros componentes, como Seguridad de PDF, solo están incluidos en el Toolkit.
- Licencia de Despliegue:
- EVO HTML a PDF: $450
- EVO PDF Toolkit: $650
- Una aplicación desplegada en un servidor, utilizada por tu propia empresa
- Desarrolladores ilimitados trabajando en esa aplicación
- Despliegues balanceados, en contenedores o escalados automáticamente necesitan una Licencia de Empresa
- Sin redistribución
- Soporte estándar primer año
- Licencia de Empresa:
- EVO HTML a PDF: $1,200
- EVO PDF Toolkit: $1,400
- Desarrolladores, aplicaciones y servidores ilimitados
- Redistribución a tus propios clientes dentro de tus aplicaciones; el acuerdo de licencia no permite ofrecer la funcionalidad de conversión como un servicio independiente, API alojada o SDK sin el permiso por escrito de EVO
- Soporte prioritario primer año
Análisis de Costo Total de Propiedad
Cada escenario a continuación establece sus suposiciones de despliegue, porque ambos proveedores fijan precios por alcance así como por tamaño de equipo:
Escenario 1: Dos Desarrolladores, Una Aplicación Interna en Un Servidor
- IronPDF Plus: $1,499 (Lite cubre 1 desarrollador, por lo que un equipo de 2 personas necesita Plus, que cubre hasta 3)
- EvoPdf Despliegue: $450 (una aplicación en un servidor; no se cuentan desarrolladores)
- Si la aplicación se ejecuta en varios servidores, detrás de un balanceador de carga o en contenedores escalados automáticamente, EvoPdf necesita la Licencia de Empresa ($1,200)
- Menor costo de licencia: EvoPdf
Escenario 2: Cinco Desarrolladores, Varias Aplicaciones Internas
- IronPDF Professional: $2,399 (hasta 10 desarrolladores, 10 ubicaciones, 10 proyectos; Plus cubre solo 3 desarrolladores)
- EvoPdf Empresa: $1,200 (más de una aplicación necesita la Licencia de Empresa)
- Menor costo de licencia: EvoPdf
Escenario 3: Diez Desarrolladores Necesitando Herramientas de PDF y Otros Documentos
- Iron Suite Professional: 10 desarrolladores, 10 ubicaciones, 10 proyectos, los 10 productos de Iron Software (ver la página de licencias de Iron Suite para el precio actual)
- EVO PDF Toolkit Empresa: $1,400 (desarrolladores, aplicaciones y servidores ilimitados; enfocado en PDF, sin herramientas de OCR o código de barras)
- Alcance diferente: el EVO PDF Toolkit cuesta menos si solo necesitas herramientas de PDF. Iron Suite agrega OCR, código de barras, Excel, Word y otras bibliotecas, que el Toolkit no reemplaza. Compara los dos solo en el alcance de desarrollador y despliegue coincidente.
Escenario 4: Producto SaaS Comercial que Genera PDFs para Sus Clientes
- IronPDF Professional + OEM redistribución: $2,399 + $1,999 (cubre SaaS donde los usuarios finales no llaman directamente a las APIs de IronPDF)
- EvoPdf Company: $1,200 (incluye redistribución; la generación de PDF debe ser una característica de su producto en lugar de un servicio de conversión de propósito general)
- Costo de licencia más bajo: EvoPdf, siempre que el producto no exponga la funcionalidad de conversión como un servicio o API pública; ambos proveedores licencian ese caso por separado
¿Cómo Afectan los Marcos de CSS Modernos a Su Elección?
Un factor a menudo subestimado en la selección de bibliotecas PDF es el soporte para marcos de CSS modernos. Con Bootstrap, Tailwind CSS y Foundation ampliamente utilizados en el desarrollo web, la capacidad de su biblioteca para manejar estos marcos impacta directamente en la eficiencia del desarrollo y la calidad del resultado.
IronPDF: El Soporte de Marcos Depende de la Versión de Chromium
El motor Chromium de IronPDF renderiza los marcos de CSS como lo hace la versión de Chromium incluida, por lo que verifique los requisitos del navegador de un marco en comparación con el paquete que envía:
- Bootstrap 5: Se admiten los diseños de Flexbox y CSS Grid
- Tailwind CSS: Tailwind CSS v4 requiere Chrome 111 o posterior, que es más reciente que el Chromium 109 del paquete estándar de Windows, por lo que en Windows los diseños v4 necesitan el paquete IronPdf.UpdatedChrome (Chromium 131). Tailwind recomienda permanecer en v3.4 donde se deben admitir navegadores más antiguos. Pruebe sus propias plantillas con el paquete que despliega.
- CSS3 Moderno: Se admiten las transformaciones y propiedades personalizadas
- La versión del motor importa: Algunos CSS más nuevos, como
subgrid, casos extremos deoverflow: hiddeny alturas de línea personalizadas, se renderizan correctamente solo con IronPdf.UpdatedChrome, que IronPDF también recomienda cuando las páginas de Bootstrap o Tailwind se renderizan lentamente. IronPdf.UpdatedChrome no admite procesos de 32 bits, Windows Server 2012 o el modoSingleProcess, así que confirme sus objetivos de implementación antes de cambiar.
Ejemplo de Código: Componente de Línea de Tiempo de Bootstrap
// NuGet: Install-Package IronPdf
using IronPdf;
var renderer = new ChromePdfRenderer();
string bootstrapTimeline = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
<style>
.timeline { position: relative; padding: 20px 0; }
.timeline::before {
content: '';
position: absolute;
left: 50%;
width: 2px;
height: 100%;
background: #dee2e6;
}
.timeline-item { position: relative; margin: 20px 0; }
</style>
</head>
<body>
<div class='container py-5'>
<h2 class='text-center mb-5'>Project Timeline</h2>
<div class='timeline'>
<div class='timeline-item'>
<div class='row'>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-body'>
<h5 class='card-title'>Phase 1: Planning</h5>
<p class='text-muted'>Q1 2025</p>
<p class='card-text'>Initial project scope and requirements gathering completed.</p>
<span class='badge bg-success'>Completed</span>
</div>
</div>
</div>
</div>
</div>
<!-- Additional timeline items... -->
</div>
</div>
</body>
</html>";
// The page loads Bootstrap from a CDN, so the renderer needs network access
using var pdf = renderer.RenderHtmlAsPdf(bootstrapTimeline);
pdf.SaveAs("project-timeline.pdf");' NuGet: Install-Package IronPdf
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim bootstrapTimeline As String = "
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
<style>
.timeline { position: relative; padding: 20px 0; }
.timeline::before {
content: '';
position: absolute;
left: 50%;
width: 2px;
height: 100%;
background: #dee2e6;
}
.timeline-item { position: relative; margin: 20px 0; }
</style>
</head>
<body>
<div class='container py-5'>
<h2 class='text-center mb-5'>Project Timeline</h2>
<div class='timeline'>
<div class='timeline-item'>
<div class='row'>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-body'>
<h5 class='card-title'>Phase 1: Planning</h5>
<p class='text-muted'>Q1 2025</p>
<p class='card-text'>Initial project scope and requirements gathering completed.</p>
<span class='badge bg-success'>Completed</span>
</div>
</div>
</div>
</div>
</div>
<!-- Additional timeline items... -->
</div>
</div>
</body>
</html>"
' The page loads Bootstrap from a CDN, so the renderer needs network access
Using pdf = renderer.RenderHtmlAsPdf(bootstrapTimeline)
pdf.SaveAs("project-timeline.pdf")
End UsingEvoPdf: Chromium en Next, Motor Propio de EVO en Classic
Las dos ediciones de EvoPdf manejan el CSS moderno de manera diferente:
- EvoPdf Next: Motor basado en Chromium (Chromium 142, según EVO PDF) con soporte documentado para flexbox, grid, JavaScript ES2015+ y fuentes web
- EvoPdf Classic: Motor de renderizado propio de EVO, que EVO describe como compatible con CSS3, SVG, fuentes web y JavaScript; la Nueva Edición agrega ECMAScript 6, WOFF 2, HTTP/2 y TLS 1.3
Impacto en el Desarrollo: Si su aplicación utiliza extensamente Bootstrap o Tailwind y necesita PDFs que coincidan con su interfaz web, pruebe sus plantillas reales con la prueba de cada biblioteca. Con motores basados en Chromium en ambos lados (IronPDF y EvoPdf Next), las diferencias son más probables debido a la versión del motor y la configuración que al soporte del marco.
Para más información sobre la compatibilidad con marcos de CSS, consulte la Guía de Bootstrap & Flexbox CSS.
¿Qué Opciones de Documentación y Soporte Sirven Mejor a los Desarrolladores?
Recursos para Desarrolladores de IronPDF
IronPDF proporciona documentación, chat en vivo 24/5, soporte de ingeniería 24/7 con Soporte Premium, tutoriales en video y actualizaciones regulares. El ecosistema de soporte incluye:
- Calidad de la Documentación:
- Referencia de API
- Tutoriales paso a paso
- 100+ ejemplos de código
- Tutoriales en video en YouTube
- Guías de migración desde otras bibliotecas
- Canales de Soporte:
- Soporte de ingeniería 24/7 con Soporte Premium, disponible para licencias pagadas; los usuarios de prueba reciben Soporte Premium durante la prueba
- SLA de respuesta por correo electrónico: 48 horas (Plus), 24 horas (Professional), 12 horas (Unlimited)
- Chat en vivo en todos los niveles de licencia, 24/5
- Soporte telefónico para licencias Professional y Unlimited
- Compartición de pantalla en licencias Professional y Unlimited
- Recursos de Aprendizaje:
- Guías de inicio
- Guías de optimización de rendimiento
- Mejores prácticas de seguridad
- Guías de implementación en la nube
Estructura de Soporte de EvoPdf
EvoPdf proporciona documentación y soporte a través de:
- Documentación:
- Documentación de referencia de API
- Ejemplos de código para escenarios comunes, además de muestras de código en GitHub
- Aplicación de demostración en línea
- Preguntas frecuentes de soporte que cubren licencias, implementación y conversión
- Opciones de Soporte:
- Soporte técnico incluido durante el primer año, y gratuito durante la evaluación
- Soporte estándar (licencia de implementación) o soporte prioritario (licencia de empresa)
- Renovaciones de mantenimiento disponibles después del primer año
La principal diferencia es la amplitud del contenido educativo de IronPDF (tutoriales, guías prácticas y videos) junto con chat en vivo 24/5 y soporte 24/7 con Soporte Premium.
¿Cuáles Son los Mejores Casos de Uso para Cada Biblioteca?
Cuándo Elegir IronPDF
IronPDF sobresale en escenarios que requieren:
1. Integración con Aplicaciones Web Modernas
- Plataformas SaaS que generan informes dinámicos
- Sitios de comercio electrónico que crean facturas con gráficos
- Paneles de inteligencia empresarial exportados como PDFs
- Aplicaciones que utilizan React, Angular o Vue.js
2. Documentos con Contenido Sensible
- Eliminación de datos personales de documentos antes de compartirlos
- Cifrado y protección con contraseña de informes generados
- Firma de documentos para que los cambios posteriores puedan ser detectados
- Gestión de documentos legales con redacción
3. Procesamiento Complejo de Documentos
- Conversión de documentos en múltiples formatos (DOCX, HTML, Imágenes)
- OCR para documentos escaneados a través de IronOCR
- Procesamiento por lotes con ejecución paralela
- Documentos con firmas digitales
4. Implementación Multiplataforma
- Aplicaciones en contenedores Docker
- Implementaciones en la nube basadas en Linux
- Arquitecturas de microservicios
- Funciones sin servidor (AWS Lambda, Azure Functions)
Ejemplo: Protección de un Informe Generado
// NuGet: Install-Package IronPdf
using System.Net;
using IronPdf;
using IronPdf.Security;
using IronPdf.Signing;
var patient = new PatientRecord("P-10442", "Jane <Q.> Doe & Family", "123-45-6789", "open-sesame");
// HTML-encode text values, so characters such as & and < print as text instead of changing the markup
var html = $@"
<html>
<body>
<h1>Patient Summary</h1>
<p>Patient ID: {WebUtility.HtmlEncode(patient.PatientId)}</p>
<p>Name: {WebUtility.HtmlEncode(patient.Name)}</p>
<p>SSN: {WebUtility.HtmlEncode(patient.Ssn)}</p>
</body>
</html>";
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderHtmlAsPdf(html);
// Remove the SSN from the page content wherever it appears
pdf.RedactTextOnAllPages(patient.Ssn);
// Descriptive document properties
pdf.MetaData.Author = "Records System";
pdf.MetaData.Title = $"Patient Summary {patient.PatientId}";
// Require a password to open the file, restrict copying, and encrypt with AES-256
pdf.SecuritySettings.UserPassword = patient.AccessCode;
pdf.SecuritySettings.OwnerPassword = "records-owner-password";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SecuritySettings.EncryptionType = PdfEncryptionType.Aes_256;
// Sign last, so changes made to the file after signing can be detected
pdf.Sign(new PdfSignature("records-cert.pfx", "password")
{
SigningReason = "Record export",
SigningLocation = "Records Department"
});
pdf.SaveAs("patient-summary.pdf");
record PatientRecord(string PatientId, string Name, string Ssn, string AccessCode);' NuGet: Install-Package IronPdf
Imports System.Net
Imports IronPdf
Imports IronPdf.Security
Imports IronPdf.Signing
Dim patient = New PatientRecord("P-10442", "Jane <Q.> Doe & Family", "123-45-6789", "open-sesame")
' HTML-encode text values, so characters such as & and < print as text instead of changing the markup
Dim html = $"
<html>
<body>
<h1>Patient Summary</h1>
<p>Patient ID: {WebUtility.HtmlEncode(patient.PatientId)}</p>
<p>Name: {WebUtility.HtmlEncode(patient.Name)}</p>
<p>SSN: {WebUtility.HtmlEncode(patient.Ssn)}</p>
</body>
</html>"
Dim renderer = New ChromePdfRenderer()
Using pdf = renderer.RenderHtmlAsPdf(html)
' Remove the SSN from the page content wherever it appears
pdf.RedactTextOnAllPages(patient.Ssn)
' Descriptive document properties
pdf.MetaData.Author = "Records System"
pdf.MetaData.Title = $"Patient Summary {patient.PatientId}"
' Require a password to open the file, restrict copying, and encrypt with AES-256
pdf.SecuritySettings.UserPassword = patient.AccessCode
pdf.SecuritySettings.OwnerPassword = "records-owner-password"
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights
pdf.SecuritySettings.EncryptionType = PdfEncryptionType.Aes_256
' Sign last, so changes made to the file after signing can be detected
pdf.Sign(New PdfSignature("records-cert.pfx", "password") With {
.SigningReason = "Record export",
.SigningLocation = "Records Department"
})
pdf.SaveAs("patient-summary.pdf")
End Using
Public Record PatientRecord(PatientId As String, Name As String, Ssn As String, AccessCode As String)Estos son bloques de construcción para el procesamiento de documentos. Si una aplicación cumple con una regulación como HIPAA también depende de cómo almacena, transmite y controla el acceso a los datos, lo cual ninguna configuración de PDF establece por sí sola.
Cuándo Elegir EvoPdf
EvoPdf es adecuado para:
1. Conversión de HTML a PDF
- Informes construidos a partir de plantillas HTML
- HTML, CSS y JavaScript modernos con el EvoPdf Next basado en Chromium
- Facturas y recibos
- Generación masiva de documentos con plantillas consistentes
2. Equipos Conscientes del Presupuesto
- Desarrolladores ilimitados en una sola licencia
- Costo de entrada más bajo ($450 licencia de implementación)
- Proyectos que no necesitan redacción incorporada
3. Entornos de Servidor Específicos
- Aplicaciones heredadas de .NET Framework (EvoPdf Classic admite .NET Framework 2.0 y posteriores)
- Licencias por servidor para una sola aplicación
- Integración con sistemas heredados
4. Conversiones de Alto Volumen
- Generación de informes estáticos
- Sistemas de documentación
- Creación de documentos listos para imprimir
Ejemplo del Mundo Real: Sistema de Generación de Facturas
// NuGet: Install-Package EvoPdf.HtmlToPdf (EvoPdf Classic, Windows)
using System;
using System.Globalization;
using System.IO;
using System.Net;
using EvoPdf;
var invoice = new InvoiceData("INV-2026-0042", new DateTime(2026, 9, 1), "Smith & Sons <Ltd>", 1250.00m);
var converter = new HtmlToPdfConverter
{
// LicenseKey = "<your EvoPdf license key>",
JavaScriptEnabled = false, // not needed for static invoices
ConversionDelay = 0
};
converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
converter.PdfDocumentOptions.TopMargin = 30; // points
converter.PdfDocumentOptions.BottomMargin = 30; // points
string template =
"<html><body><h1>Invoice {{InvoiceNumber}}</h1>" +
"<p>Date: {{Date}}</p><p>Customer: {{CustomerName}}</p><p>Total: {{Total}}</p></body></html>";
// HTML-encode text values, so characters such as & and < print as text instead of changing the markup
string html = template
.Replace("{{InvoiceNumber}}", WebUtility.HtmlEncode(invoice.InvoiceNumber))
.Replace("{{Date}}", invoice.Date.ToString("yyyy-MM-dd"))
.Replace("{{CustomerName}}", WebUtility.HtmlEncode(invoice.CustomerName))
.Replace("{{Total}}", invoice.Total.ToString("C", CultureInfo.GetCultureInfo("en-US")));
File.WriteAllBytes($"invoice-{invoice.InvoiceNumber}.pdf", converter.ConvertHtml(html, ""));
record InvoiceData(string InvoiceNumber, DateTime Date, string CustomerName, decimal Total);' NuGet: Install-Package EvoPdf.HtmlToPdf (EvoPdf Classic, Windows)
Imports System
Imports System.Globalization
Imports System.IO
Imports System.Net
Imports EvoPdf
Dim invoice = New InvoiceData("INV-2026-0042", New DateTime(2026, 9, 1), "Smith & Sons <Ltd>", 1250.00D)
Dim converter = New HtmlToPdfConverter With {
' LicenseKey = "<your EvoPdf license key>",
.JavaScriptEnabled = False, ' not needed for static invoices
.ConversionDelay = 0
}
converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4
converter.PdfDocumentOptions.TopMargin = 30 ' points
converter.PdfDocumentOptions.BottomMargin = 30 ' points
Dim template As String =
"<html><body><h1>Invoice {{InvoiceNumber}}</h1>" +
"<p>Date: {{Date}}</p><p>Customer: {{CustomerName}}</p><p>Total: {{Total}}</p></body></html>"
' HTML-encode text values, so characters such as & and < print as text instead of changing the markup
Dim html As String = template _
.Replace("{{InvoiceNumber}}", WebUtility.HtmlEncode(invoice.InvoiceNumber)) _
.Replace("{{Date}}", invoice.Date.ToString("yyyy-MM-dd")) _
.Replace("{{CustomerName}}", WebUtility.HtmlEncode(invoice.CustomerName)) _
.Replace("{{Total}}", invoice.Total.ToString("C", CultureInfo.GetCultureInfo("en-US")))
File.WriteAllBytes($"invoice-{invoice.InvoiceNumber}.pdf", converter.ConvertHtml(html, ""))
Public Class InvoiceData
Public Property InvoiceNumber As String
Public Property Date As DateTime
Public Property CustomerName As String
Public Property Total As Decimal
Public Sub New(invoiceNumber As String, [date] As DateTime, customerName As String, total As Decimal)
Me.InvoiceNumber = invoiceNumber
Me.Date = [date]
Me.CustomerName = customerName
Me.Total = total
End Sub
End ClassPatrones de Implementación Avanzados y Mejores Prácticas
Optimización del Rendimiento en Producción
Ambas bibliotecas se benefician de una configuración y patrones de uso adecuados:
Optimización del Rendimiento de IronPDF
// NuGet: Install-Package IronPdf
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using IronPdf;
using IronPdf.Engines.Chrome;
using IronPdf.Rendering;
// Global engine settings: set once at startup, before the first render
Installation.ChromeGpuMode = ChromeGpuModes.Disabled; // servers usually have no GPU
// Set to false only if the Linux dependencies are already installed in your image
Installation.LinuxAndDockerDependenciesAutoConfig = false;
var service = new PdfService(maxConcurrency: 4);
var pages = Enumerable.Range(1, 8).Select(i => $"<h1>Report {i}</h1>");
byte[][] results = await Task.WhenAll(pages.Select(service.GeneratePdfAsync));
for (int i = 0; i < results.Length; i++)
File.WriteAllBytes($"report-{i + 1}.pdf", results[i]);
Console.WriteLine($"Generated {results.Length} PDFs");
public class PdfService
{
private readonly ChromePdfRenderer _renderer;
private readonly SemaphoreSlim _gate;
public PdfService(int maxConcurrency)
{
// Caps how many renders run at once
_gate = new SemaphoreSlim(maxConcurrency);
_renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
EnableJavaScript = false, // only if the pages need no JavaScript
CssMediaType = PdfCssMediaType.Screen,
Timeout = 30 // seconds
}
};
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
await _gate.WaitAsync();
try
{
using var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
finally
{
_gate.Release();
}
}
}Imports System
Imports System.IO
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks
Imports IronPdf
Imports IronPdf.Engines.Chrome
Imports IronPdf.Rendering
' Global engine settings: set once at startup, before the first render
Installation.ChromeGpuMode = ChromeGpuModes.Disabled ' servers usually have no GPU
' Set to false only if the Linux dependencies are already installed in your image
Installation.LinuxAndDockerDependenciesAutoConfig = False
Dim service = New PdfService(MaxConcurrency:=4)
Dim pages = Enumerable.Range(1, 8).Select(Function(i) $"<h1>Report {i}</h1>")
Dim results As Byte()() = Await Task.WhenAll(pages.Select(Function(page) service.GeneratePdfAsync(page)))
For i As Integer = 0 To results.Length - 1
File.WriteAllBytes($"report-{i + 1}.pdf", results(i))
Next
Console.WriteLine($"Generated {results.Length} PDFs")
Public Class PdfService
Private ReadOnly _renderer As ChromePdfRenderer
Private ReadOnly _gate As SemaphoreSlim
Public Sub New(maxConcurrency As Integer)
' Caps how many renders run at once
_gate = New SemaphoreSlim(maxConcurrency)
_renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.EnableJavaScript = False, ' only if the pages need no JavaScript
.CssMediaType = PdfCssMediaType.Screen,
.Timeout = 30 ' seconds
}
}
End Sub
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Await _gate.WaitAsync()
Try
Using pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Using
Finally
_gate.Release()
End Try
End Function
End ClassPatrones de Rendimiento de EvoPdf
// NuGet: Install-Package EvoPdf.HtmlToPdf (EvoPdf Classic, Windows)
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EvoPdf;
var service = new EvoPdfService(maxConcurrency: 4);
var pages = Enumerable.Range(1, 8).Select(i => $"<h1>Report {i}</h1>");
byte[][] results = await Task.WhenAll(pages.Select(service.GeneratePdfAsync));
for (int i = 0; i < results.Length; i++)
File.WriteAllBytes($"evopdf-report-{i + 1}.pdf", results[i]);
Console.WriteLine($"Generated {results.Length} PDFs");
public class EvoPdfService
{
private readonly SemaphoreSlim _gate;
// Caps how many conversions run at once
public EvoPdfService(int maxConcurrency) => _gate = new SemaphoreSlim(maxConcurrency);
public async Task<byte[]> GeneratePdfAsync(string html)
{
await _gate.WaitAsync();
try
{
// A new converter for each conversion, as EVO documents for parallel conversions
var converter = new HtmlToPdfConverter
{
// LicenseKey = "<your EvoPdf license key>",
JavaScriptEnabled = false,
ConversionDelay = 0
};
// The Classic API is synchronous, so run it on a thread-pool thread
return await Task.Run(() => converter.ConvertHtml(html, ""));
}
finally
{
_gate.Release();
}
}
}Imports System
Imports System.IO
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks
Imports EvoPdf
Dim service = New EvoPdfService(maxConcurrency:=4)
Dim pages = Enumerable.Range(1, 8).[Select](Function(i) $"<h1>Report {i}</h1>")
Dim results As Byte()() = Await Task.WhenAll(pages.[Select](Function(page) service.GeneratePdfAsync(page)))
For i As Integer = 0 To results.Length - 1
File.WriteAllBytes($"evopdf-report-{i + 1}.pdf", results(i))
Next
Console.WriteLine($"Generated {results.Length} PDFs")
Public Class EvoPdfService
Private ReadOnly _gate As SemaphoreSlim
' Caps how many conversions run at once
Public Sub New(maxConcurrency As Integer)
_gate = New SemaphoreSlim(maxConcurrency)
End Sub
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Await _gate.WaitAsync()
Try
' A new converter for each conversion, as EVO documents for parallel conversions
Dim converter = New HtmlToPdfConverter With {
' LicenseKey = "<your EvoPdf license key>",
.JavaScriptEnabled = False,
.ConversionDelay = 0
}
' The Classic API is synchronous, so run it on a thread-pool thread
Return Await Task.Run(Function() converter.ConvertHtml(html, ""))
Finally
_gate.Release()
End Try
End Function
End ClassEl semáforo es lo que limita la concurrencia en ambos ejemplos. En EvoPdf Next, GlobalSettings.MaxParallelConversions establece el mismo tipo de límite dentro de la biblioteca, y el renderizador persistente mantiene el proceso del motor de renderizado en ejecución entre conversiones.
Manejo de Errores y Depuración
El código de producción necesita manejar fallos de renderizado, como una página que no se puede cargar:
Manejo de Errores de IronPDF
// NuGet: Install-Package IronPdf
using System;
using System.IO;
using System.Threading.Tasks;
using IronPdf;
using IronPdf.Exceptions;
// Write IronPDF's own diagnostics to a log file
IronPdf.Logging.Logger.LogFilePath = "ironpdf.log";
IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.Timeout = 60; // seconds
byte[] page = await TryRenderUrlAsync(renderer, "https://example.com/");
if (page != null)
{
File.WriteAllBytes("example.pdf", page);
Console.WriteLine($"Rendered {page.Length} bytes");
}
// A host that does not resolve makes the render throw, which exercises the error path
byte[] missing = await TryRenderUrlAsync(renderer, "https://nonexistent.invalid/");
Console.WriteLine(missing == null ? "Second render failed and was handled" : "Second render succeeded");
// Returns the PDF bytes, or null if the page could not be rendered
static async Task<byte[]> TryRenderUrlAsync(ChromePdfRenderer renderer, string url)
{
try
{
using var pdf = await renderer.RenderUrlAsPdfAsync(url);
if (pdf.PageCount == 0)
{
Console.Error.WriteLine($"No pages rendered for {url}");
return null;
}
return pdf.BinaryData;
}
catch (IronPdfNativeException ex)
{
// Raised by the rendering engine, for example when the page cannot be loaded
Console.Error.WriteLine($"Rendering failed for {url}: {ex.Message}");
return null;
}
}' NuGet: Install-Package IronPdf
Imports System
Imports System.IO
Imports System.Threading.Tasks
Imports IronPdf
Imports IronPdf.Exceptions
' Write IronPDF's own diagnostics to a log file
IronPdf.Logging.Logger.LogFilePath = "ironpdf.log"
IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.Timeout = 60 ' seconds
Dim page As Byte() = Await TryRenderUrlAsync(renderer, "https://example.com/")
If page IsNot Nothing Then
File.WriteAllBytes("example.pdf", page)
Console.WriteLine($"Rendered {page.Length} bytes")
End If
' A host that does not resolve makes the render throw, which exercises the error path
Dim missing As Byte() = Await TryRenderUrlAsync(renderer, "https://nonexistent.invalid/")
Console.WriteLine(If(missing Is Nothing, "Second render failed and was handled", "Second render succeeded"))
' Returns the PDF bytes, or null if the page could not be rendered
Private Shared Async Function TryRenderUrlAsync(renderer As ChromePdfRenderer, url As String) As Task(Of Byte())
Try
Using pdf = Await renderer.RenderUrlAsPdfAsync(url)
If pdf.PageCount = 0 Then
Console.Error.WriteLine($"No pages rendered for {url}")
Return Nothing
End If
Return pdf.BinaryData
End Using
Catch ex As IronPdfNativeException
' Raised by the rendering engine, for example when the page cannot be loaded
Console.Error.WriteLine($"Rendering failed for {url}: {ex.Message}")
Return Nothing
End Try
End FunctionEjemplos de Implementación Específicos de la Industria
Informes Financieros: Declaraciones Firmadas y de Solo Lectura
Una declaración que no debería cambiar después de la aprobación puede combinar una marca de agua, permisos restringidos y una firma:
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Editing;
using IronPdf.Security;
using IronPdf.Signing;
using IronSoftware.Drawing;
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderHtmlAsPdf(
"<h1>Quarterly Statement: Q3 2026</h1>" +
"<table><tr><td>Revenue</td><td>1,250,000</td></tr><tr><td>Expenses</td><td>980,000</td></tr></table>");
// Mark the document as a draft
pdf.ApplyWatermark(@"
<div style='color: rgba(0,0,0,0.1); font-size: 120px; transform: rotate(-45deg); font-family: Arial;'>
DRAFT
</div>", 30, VerticalAlignment.Middle, HorizontalAlignment.Center);
// Descriptive document properties: useful for search and filing, not a record of who changed what
pdf.MetaData.Author = "Financial Reporting System";
pdf.MetaData.Keywords = "Quarterly Statement, Q3 2026";
pdf.MetaData.CustomProperties.Add("ReportPeriod", "2026-Q3");
pdf.MetaData.CustomProperties.Add("GeneratedAt", DateTime.UtcNow.ToString("O"));
// Restrict editing; the owner password is needed to change these permissions
pdf.SecuritySettings.OwnerPassword = "finance-owner-password";
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;
pdf.SecuritySettings.AllowUserCopyPasteContent = true;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SecuritySettings.EncryptionType = PdfEncryptionType.Aes_256;
// Sign last: readers can then detect changes made after signing
pdf.Sign(new PdfSignature("financial-cert.pfx", "password")
{
SigningReason = "Statement approval",
SigningLocation = "Finance Department",
// Visible signature image on the first page
SignatureImage = new PdfSignatureImage("cfo-signature.png", 0, new Rectangle(50, 50, 200, 60))
});
pdf.SaveAs("quarterly-statement.pdf");' NuGet: Install-Package IronPdf
Imports System
Imports IronPdf
Imports IronPdf.Editing
Imports IronPdf.Security
Imports IronPdf.Signing
Imports IronSoftware.Drawing
Dim renderer = New ChromePdfRenderer()
Using pdf = renderer.RenderHtmlAsPdf(
"<h1>Quarterly Statement: Q3 2026</h1>" &
"<table><tr><td>Revenue</td><td>1,250,000</td></tr><tr><td>Expenses</td><td>980,000</td></tr></table>")
' Mark the document as a draft
pdf.ApplyWatermark("
<div style='color: rgba(0,0,0,0.1); font-size: 120px; transform: rotate(-45deg); font-family: Arial;'>
DRAFT
</div>", 30, VerticalAlignment.Middle, HorizontalAlignment.Center)
' Descriptive document properties: useful for search and filing, not a record of who changed what
pdf.MetaData.Author = "Financial Reporting System"
pdf.MetaData.Keywords = "Quarterly Statement, Q3 2026"
pdf.MetaData.CustomProperties.Add("ReportPeriod", "2026-Q3")
pdf.MetaData.CustomProperties.Add("GeneratedAt", DateTime.UtcNow.ToString("O"))
' Restrict editing; the owner password is needed to change these permissions
pdf.SecuritySettings.OwnerPassword = "finance-owner-password"
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit
pdf.SecuritySettings.AllowUserCopyPasteContent = True
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights
pdf.SecuritySettings.EncryptionType = PdfEncryptionType.Aes_256
' Sign last: readers can then detect changes made after signing
pdf.Sign(New PdfSignature("financial-cert.pfx", "password") With {
.SigningReason = "Statement approval",
.SigningLocation = "Finance Department",
' Visible signature image on the first page
.SignatureImage = New PdfSignatureImage("cfo-signature.png", 0, New Rectangle(50, 50, 200, 60))
})
pdf.SaveAs("quarterly-statement.pdf")
End UsingLa firma hace que los cambios posteriores sean detectables y los permisos desaconsejan la edición; ninguno es, por sí solo, un control de cumplimiento o una pista de auditoría de quién hizo qué.
Comercio Electrónico: Generación Dinámica de Facturas
Las plataformas de comercio electrónico necesitan una generación de facturas rápida y confiable:
// NuGet: Install-Package IronPdf
using System;
using System.Globalization;
using System.Linq;
using System.Net;
using IronPdf;
using IronPdf.Rendering;
var order = new Order("INV-1001", new DateTime(2026, 9, 1), new[]
{
new OrderItem("Widget <Deluxe> & Co. edition", 2, 19.99m),
new OrderItem("Gift wrap", 1, 4.50m)
});
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
MarginTop = 10, // millimetres
MarginBottom = 10,
PaperSize = PdfPaperSize.A4
}
};
var usd = CultureInfo.GetCultureInfo("en-US");
// HTML-encode text values, so characters such as & and < print as text instead of changing the markup
string rows = string.Concat(order.Items.Select(item => $@"
<tr>
<td>{WebUtility.HtmlEncode(item.Name)}</td>
<td>{item.Quantity}</td>
<td>{item.Price.ToString("C", usd)}</td>
<td>{item.Total.ToString("C", usd)}</td>
</tr>"));
var html = $@"
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{ background: #f0f0f0; padding: 20px; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ padding: 10px; border-bottom: 1px solid #ddd; text-align: left; }}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{WebUtility.HtmlEncode(order.InvoiceNumber)}</h1>
<p>Date: {order.Date:yyyy-MM-dd}</p>
</div>
<table>
<tr><th>Item</th><th>Quantity</th><th>Price</th><th>Total</th></tr>
{rows}
<tr><td colspan='3'><strong>Total</strong></td><td><strong>{order.Total.ToString("C", usd)}</strong></td></tr>
</table>
<p>Thank you for your business!</p>
</body>
</html>";
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
pdf.SaveAs($"invoice-{order.InvoiceNumber}.pdf");
record OrderItem(string Name, int Quantity, decimal Price)
{
public decimal Total => Price * Quantity;
}
record Order(string InvoiceNumber, DateTime Date, OrderItem[] Items)
{
public decimal Total => Items.Sum(item => item.Total);
}' NuGet: Install-Package IronPdf
Imports System
Imports System.Globalization
Imports System.Linq
Imports System.Net
Imports IronPdf
Imports IronPdf.Rendering
Dim order = New Order("INV-1001", New DateTime(2026, 9, 1), {
New OrderItem("Widget <Deluxe> & Co. edition", 2, 19.99D),
New OrderItem("Gift wrap", 1, 4.5D)
})
Dim renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.MarginTop = 10, ' millimetres
.MarginBottom = 10,
.PaperSize = PdfPaperSize.A4
}
}
Dim usd = CultureInfo.GetCultureInfo("en-US")
' HTML-encode text values, so characters such as & and < print as text instead of changing the markup
Dim rows As String = String.Concat(order.Items.Select(Function(item) $"
<tr>
<td>{WebUtility.HtmlEncode(item.Name)}</td>
<td>{item.Quantity}</td>
<td>{item.Price.ToString("C", usd)}</td>
<td>{item.Total.ToString("C", usd)}</td>
</tr>"))
Dim html = $"
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{ background: #f0f0f0; padding: 20px; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ padding: 10px; border-bottom: 1px solid #ddd; text-align: left; }}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{WebUtility.HtmlEncode(order.InvoiceNumber)}</h1>
<p>Date: {order.Date:yyyy-MM-dd}</p>
</div>
<table>
<tr><th>Item</th><th>Quantity</th><th>Price</th><th>Total</th></tr>
{rows}
<tr><td colspan='3'><strong>Total</strong></td><td><strong>{order.Total.ToString("C", usd)}</strong></td></tr>
</table>
<p>Thank you for your business!</p>
</body>
</html>"
Using pdf = Await renderer.RenderHtmlAsPdfAsync(html)
pdf.SaveAs($"invoice-{order.InvoiceNumber}.pdf")
End Using
Public Record OrderItem(Name As String, Quantity As Integer, Price As Decimal)
Public ReadOnly Property Total As Decimal
Get
Return Price * Quantity
End Get
End Property
End Record
Public Record Order(InvoiceNumber As String, [Date] As DateTime, Items As OrderItem())
Public ReadOnly Property Total As Decimal
Get
Return Items.Sum(Function(item) item.Total)
End Get
End Property
End RecordEstrategias de Migración: Cambiando Entre Bibliotecas
Si está considerando cambiar entre bibliotecas, aquí hay un enfoque de migración:
Migrando de EvoPdf a IronPDF
// NuGet: Install-Package EvoPdf.HtmlToPdf (EvoPdf Classic, Windows)
// NuGet: Install-Package IronPdf
using System.IO;
using EvoPdf;
using IronPdf;
using IronPdf.Rendering;
string url = "https://example.com/";
// EvoPdf pattern
HtmlToPdfConverter evoPdfConverter = new HtmlToPdfConverter();
evoPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
File.WriteAllBytes("evopdf.pdf", evoPdfConverter.ConvertUrl(url));
// Equivalent IronPDF pattern
var ironPdfRenderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
PaperSize = PdfPaperSize.A4
}
};
using (var pdf = ironPdfRenderer.RenderUrlAsPdf(url))
{
File.WriteAllBytes("ironpdf.pdf", pdf.BinaryData);
}
// During a gradual migration, both libraries can sit behind one interface
IPdfConverter converter = new IronPdfAdapter();
File.WriteAllBytes("adapter.pdf", converter.ConvertUrlToPdf(url));
public interface IPdfConverter
{
byte[] ConvertHtmlToPdf(string html);
byte[] ConvertUrlToPdf(string url);
}
public class IronPdfAdapter : IPdfConverter
{
private readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();
public byte[] ConvertHtmlToPdf(string html)
{
using var pdf = _renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
public byte[] ConvertUrlToPdf(string url)
{
using var pdf = _renderer.RenderUrlAsPdf(url);
return pdf.BinaryData;
}
}
public class EvoPdfAdapter : IPdfConverter
{
private readonly HtmlToPdfConverter _converter = new HtmlToPdfConverter();
public byte[] ConvertHtmlToPdf(string html)
{
return _converter.ConvertHtml(html, "");
}
public byte[] ConvertUrlToPdf(string url)
{
return _converter.ConvertUrl(url);
}
}Imports System.IO
Imports EvoPdf
Imports IronPdf
Imports IronPdf.Rendering
Dim url As String = "https://example.com/"
' EvoPdf pattern
Dim evoPdfConverter As New HtmlToPdfConverter()
evoPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4
File.WriteAllBytes("evopdf.pdf", evoPdfConverter.ConvertUrl(url))
' Equivalent IronPDF pattern
Dim ironPdfRenderer As New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.PaperSize = PdfPaperSize.A4
}
}
Using pdf = ironPdfRenderer.RenderUrlAsPdf(url)
File.WriteAllBytes("ironpdf.pdf", pdf.BinaryData)
End Using
' During a gradual migration, both libraries can sit behind one interface
Dim converter As IPdfConverter = New IronPdfAdapter()
File.WriteAllBytes("adapter.pdf", converter.ConvertUrlToPdf(url))
Public Interface IPdfConverter
Function ConvertHtmlToPdf(html As String) As Byte()
Function ConvertUrlToPdf(url As String) As Byte()
End Interface
Public Class IronPdfAdapter
Implements IPdfConverter
Private ReadOnly _renderer As New ChromePdfRenderer()
Public Function ConvertHtmlToPdf(html As String) As Byte() Implements IPdfConverter.ConvertHtmlToPdf
Using pdf = _renderer.RenderHtmlAsPdf(html)
Return pdf.BinaryData
End Using
End Function
Public Function ConvertUrlToPdf(url As String) As Byte() Implements IPdfConverter.ConvertUrlToPdf
Using pdf = _renderer.RenderUrlAsPdf(url)
Return pdf.BinaryData
End Using
End Function
End Class
Public Class EvoPdfAdapter
Implements IPdfConverter
Private ReadOnly _converter As New HtmlToPdfConverter()
Public Function ConvertHtmlToPdf(html As String) As Byte() Implements IPdfConverter.ConvertHtmlToPdf
Return _converter.ConvertHtml(html, "")
End Function
Public Function ConvertUrlToPdf(url As String) As Byte() Implements IPdfConverter.ConvertUrlToPdf
Return _converter.ConvertUrl(url)
End Function
End ClassConclusión: Tomando la Decisión Correcta para Su Proyecto
Tanto IronPDF como EvoPdf desempeñan roles importantes en el ecosistema de bibliotecas PDF de .NET, pero apuntan a diferentes casos de uso y filosofías de desarrollo.
Elija IronPDF cuando necesite:
- Soporte para estándares web modernos (CSS3, marcos de JavaScript)
- Manipulación de PDF más allá de la generación, como fusión, formularios, redacción y firma
- Funciones de seguridad como cifrado, firmas y redacción
- Flexibilidad de implementación multiplataforma
- Documentación extensa y soporte directo de ingeniería
- Integración con otras herramientas de procesamiento de documentos
Elija EvoPdf cuando necesite:
- Conversión de HTML a PDF a un costo de licencia más bajo
- Licencias por aplicación (Implementación) o licencias para toda la empresa (Empresa), con redistribución en sus propias aplicaciones incluida en la licencia de Empresa
- Licencias que no cuentan desarrolladores
- Una elección entre un motor basado en Chromium (EvoPdf Next) y un motor de Windows que admite .NET Framework 2.0 y posteriores (EvoPdf Classic)
La decisión depende en última instancia de sus requisitos específicos, restricciones presupuestarias y necesidades de escalabilidad a largo plazo. Para aplicaciones modernas que necesitan manipulación de PDF más allá de la generación, como redacción incorporada y conversión de DOCX, el conjunto de características y la documentación de IronPDF lo convierten en una inversión sólida. EvoPdf es una opción viable también, particularmente para equipos que valoran su licencia para toda la empresa y la redistribución incluida.
Considere comenzar con la prueba gratuita de 30 días de IronPDF para evaluar sus capacidades en su caso de uso específico. La prueba proporciona acceso a las características de IronPDF, permitiéndole tomar una decisión informada basada en el rendimiento real en su entorno.
Recuerde que el costo real de una biblioteca PDF se extiende más allá del precio de la licencia: tenga en cuenta el tiempo de desarrollo, el mantenimiento y la posible necesidad de características adicionales a medida que su aplicación crece. Elija la biblioteca que no solo satisfaga sus necesidades actuales, sino que pueda escalar con sus requisitos futuros.
Jacob Mellor es Director de Tecnología de Iron Software y un ingeniero visionario pionero en la tecnología C# PDF. Como desarrollador original de la base de código principal de Iron Software, ha dado forma a la arquitectura de productos de la empresa desde su creación, transformándola, junto con el director ejecutivo Cameron Rimington, en una empresa de más de 50 personas que presta servicios a la NASA, Tesla y organismos gubernamentales de todo el mundo.
Artículos Relacionados


