ASP.NET Core: Crear PDF sobre la marcha con IronPDF
Genere documentos PDF profesionales de forma dinámica en ASP.NET Core convirtiendo contenido HTML en archivos PDF pulidos y transmitiéndolos directamente al navegador: no se requiere almacenamiento en disco ni archivos temporales que administrar.
Al crear aplicaciones web modernas en ASP.NET Core, la capacidad de producir documentos PDF a pedido es un requisito recurrente. Las facturas deben descargarse en el momento en que se liquida el pago. Los informes de cumplimiento deben aparecer al instante cuando un auditor haga clic en "Exportar". Los certificados deben estar listos antes de que el usuario tenga tiempo de preguntarse si algo salió mal. IronPDF maneja todos estos escenarios a través de su biblioteca PDF basada en Chromium, que convierte HTML (incluidos CSS, JavaScript y fuentes web) en una salida PDF con precisión de píxeles sin escribir nada en el disco.
Esta guía cubre todo lo que necesita saber: instalar la biblioteca, generar facturas a partir de cadenas HTML, transmitir informes a partir de datos de Entity Framework, aplicar encabezados de página y configuraciones de seguridad, y adoptar las mejores prácticas que mantienen el buen funcionamiento de las aplicaciones ASP.NET de alto tráfico.
¿Qué significa crear archivos PDF sobre la marcha?
"Al vuelo" significa que el documento se construye en la memoria en el momento de la solicitud HTTP y se envía directamente al llamador. Ningún archivo PDF se escribe en el sistema de archivos, ningún trabajo en segundo plano pone en cola el trabajo y ningún caché almacena el resultado entre solicitudes.
Este enfoque es importante por varias razones. En primer lugar, los objetivos de implementación en la nube (Azure App Service, AWS Lambda, contenedores Docker) a menudo se ejecutan en entornos donde el sistema de archivos local es efímero o de solo lectura. Generar un PDF en una carpeta temporal y luego volver a leerlo es frágil en estos entornos. En segundo lugar, evitar escrituras en disco reduce la superficie de ataque: no hay ningún archivo residual que una solicitud posterior pueda servir accidentalmente al usuario equivocado. En tercer lugar, la generación de solo memoria suele ser más rápida porque elimina dos operaciones de E/S (escritura y lectura) en la ruta crítica.
ChromePdfRenderer de IronPDF expone una propiedad .BinaryData y una propiedad .Stream en cada documento generado. Cualquiera de ellos se puede pasar directamente a un ASP.NET Core FileResult, lo que hace que la transmisión sea de una sola línea en la práctica.
¿Cómo instalar IronPDF en un proyecto ASP.NET Core ?
Agregue el paquete NuGet a través de la Consola del Administrador de paquetes o la CLI de .NET :
Install-Package IronPdf
dotnet add package IronPdf
Install-Package IronPdf
dotnet add package IronPdf
Una vez instalado el paquete, configure su clave de licencia al iniciar la aplicación, generalmente en Program.cs antes de que se cree el primer renderizador:
using IronPdf;
// Place license activation before any IronPDF call
License.LicenseKey = "YOUR-LICENSE-KEY";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
// Register ChromePdfRenderer as a singleton so the Chromium engine
// is initialised once and reused across all requests.
builder.Services.AddSingleton<ChromePdfRenderer>();
var app = builder.Build();
app.MapDefaultControllerRoute();
app.Run();
using IronPdf;
// Place license activation before any IronPDF call
License.LicenseKey = "YOUR-LICENSE-KEY";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
// Register ChromePdfRenderer as a singleton so the Chromium engine
// is initialised once and reused across all requests.
builder.Services.AddSingleton<ChromePdfRenderer>();
var app = builder.Build();
app.MapDefaultControllerRoute();
app.Run();
Imports IronPdf
' Place license activation before any IronPDF call
License.LicenseKey = "YOUR-LICENSE-KEY"
Dim builder = WebApplication.CreateBuilder(args)
builder.Services.AddControllersWithViews()
' Register ChromePdfRenderer as a singleton so the Chromium engine
' is initialised once and reused across all requests.
builder.Services.AddSingleton(Of ChromePdfRenderer)()
Dim app = builder.Build()
app.MapDefaultControllerRoute()
app.Run()
Es importante registrar ChromePdfRenderer como singleton. El renderizador inicia un subproceso interno de Chromium la primera vez que se utiliza. Si crea una nueva instancia por solicitud, paga ese costo de inicio en cada llamada, lo que agrega cientos de milisegundos de latencia bajo carga. Una instancia singleton es segura para subprocesos y maneja solicitudes de representación simultáneas sin configuración adicional.
Para obtener una visión más amplia de las opciones de instalación, incluidas las configuraciones de NuGet.config para feeds privados, visita la descripción general de la instalación .
¿Cómo generar una factura PDF a partir de una cadena HTML?
El caso de uso más común sobre la marcha es la generación de documentos transaccionales (facturas, recibos, confirmaciones de pedidos), donde el contenido cambia según la solicitud, pero el diseño permanece constante.
El patrón es: construir una cadena HTML con datos interpolados, pasarla a RenderHtmlAsPdf y devolver el resultado binario como una descarga de archivo.
using IronPdf;
using Microsoft.AspNetCore.Mvc;
public class DocumentController : Controller
{
private readonly ChromePdfRenderer _renderer;
public DocumentController(ChromePdfRenderer renderer)
{
_renderer = renderer;
}
[HttpGet("invoice/{orderId:int}")]
public IActionResult GetInvoice(int orderId)
{
// In a real application, fetch this from your database or order service.
var order = GetOrderData(orderId);
string html = $"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {{ font-family: Arial, sans-serif; margin: 40px; color: #333; }}
h1 {{ color: #1a56db; }}
table {{ width: 100%; border-collapse: collapse; margin-top: 24px; }}
th, td {{ padding: 10px 14px; border: 1px solid #d1d5db; text-align: left; }}
th {{ background: #f3f4f6; }}
tfoot td {{ font-weight: bold; }}
</style>
</head>
<body>
<h1>Invoice #{order.InvoiceNumber}</h1>
<p>Date: {DateTime.UtcNow:yyyy-MM-dd} | Customer: {order.CustomerName}</p>
<table>
<thead><tr><th>Item</th><th>Qty</th><th>Unit Price</th><th>Subtotal</th></tr></thead>
<tbody>
{string.Join("", order.Items.Select(i =>
$"<tr><td>{i.Name}</td><td>{i.Quantity}</td>" +
$"<td>${i.UnitPrice:F2}</td><td>${i.Quantity * i.UnitPrice:F2}</td></tr>"))}
</tbody>
<tfoot>
<tr><td colspan="3">Total</td><td>${order.Items.Sum(i => i.Quantity * i.UnitPrice):F2}</td></tr>
</tfoot>
</table>
</body>
</html>
""";
var pdf = _renderer.RenderHtmlAsPdf(html);
return File(pdf.BinaryData, "application/pdf", $"invoice-{orderId}.pdf");
}
}
using IronPdf;
using Microsoft.AspNetCore.Mvc;
public class DocumentController : Controller
{
private readonly ChromePdfRenderer _renderer;
public DocumentController(ChromePdfRenderer renderer)
{
_renderer = renderer;
}
[HttpGet("invoice/{orderId:int}")]
public IActionResult GetInvoice(int orderId)
{
// In a real application, fetch this from your database or order service.
var order = GetOrderData(orderId);
string html = $"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {{ font-family: Arial, sans-serif; margin: 40px; color: #333; }}
h1 {{ color: #1a56db; }}
table {{ width: 100%; border-collapse: collapse; margin-top: 24px; }}
th, td {{ padding: 10px 14px; border: 1px solid #d1d5db; text-align: left; }}
th {{ background: #f3f4f6; }}
tfoot td {{ font-weight: bold; }}
</style>
</head>
<body>
<h1>Invoice #{order.InvoiceNumber}</h1>
<p>Date: {DateTime.UtcNow:yyyy-MM-dd} | Customer: {order.CustomerName}</p>
<table>
<thead><tr><th>Item</th><th>Qty</th><th>Unit Price</th><th>Subtotal</th></tr></thead>
<tbody>
{string.Join("", order.Items.Select(i =>
$"<tr><td>{i.Name}</td><td>{i.Quantity}</td>" +
$"<td>${i.UnitPrice:F2}</td><td>${i.Quantity * i.UnitPrice:F2}</td></tr>"))}
</tbody>
<tfoot>
<tr><td colspan="3">Total</td><td>${order.Items.Sum(i => i.Quantity * i.UnitPrice):F2}</td></tr>
</tfoot>
</table>
</body>
</html>
""";
var pdf = _renderer.RenderHtmlAsPdf(html);
return File(pdf.BinaryData, "application/pdf", $"invoice-{orderId}.pdf");
}
}
Imports IronPdf
Imports Microsoft.AspNetCore.Mvc
Public Class DocumentController
Inherits Controller
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New(renderer As ChromePdfRenderer)
_renderer = renderer
End Sub
<HttpGet("invoice/{orderId:int}")>
Public Function GetInvoice(orderId As Integer) As IActionResult
' In a real application, fetch this from your database or order service.
Dim order = GetOrderData(orderId)
Dim html As String = $"
<!DOCTYPE html>
<html lang=""en"">
<head>
<meta charset=""utf-8"">
<style>
body {{ font-family: Arial, sans-serif; margin: 40px; color: #333; }}
h1 {{ color: #1a56db; }}
table {{ width: 100%; border-collapse: collapse; margin-top: 24px; }}
th, td {{ padding: 10px 14px; border: 1px solid #d1d5db; text-align: left; }}
th {{ background: #f3f4f6; }}
tfoot td {{ font-weight: bold; }}
</style>
</head>
<body>
<h1>Invoice #{order.InvoiceNumber}</h1>
<p>Date: {DateTime.UtcNow:yyyy-MM-dd} | Customer: {order.CustomerName}</p>
<table>
<thead><tr><th>Item</th><th>Qty</th><th>Unit Price</th><th>Subtotal</th></tr></thead>
<tbody>
{String.Join("", order.Items.Select(Function(i) $"<tr><td>{i.Name}</td><td>{i.Quantity}</td>" +
$"<td>${i.UnitPrice:F2}</td><td>${i.Quantity * i.UnitPrice:F2}</td></tr>"))}
</tbody>
<tfoot>
<tr><td colspan=""3"">Total</td><td>${order.Items.Sum(Function(i) i.Quantity * i.UnitPrice):F2}</td></tr>
</tfoot>
</table>
</body>
</html>
"
Dim pdf = _renderer.RenderHtmlAsPdf(html)
Return File(pdf.BinaryData, "application/pdf", $"invoice-{orderId}.pdf")
End Function
End Class
RenderHtmlAsPdf procesa el documento HTML completo (cuadrícula CSS, Flexbox, fuentes web, incluso SVG en línea) utilizando el mismo motor Chromium que impulsa Google Chrome. El PdfDocument devuelto expone BinaryData (un byte[]) y Stream (un MemoryStream). Pasar BinaryData a File() con "application/pdf" y un nombre de archivo activa una descarga del navegador.
Para diseños que necesitan fidelidad de píxeles perfecta, consulte la guía de renderizado de HTML a PDF que cubre CSS responsivo, fuentes personalizadas y renderizado de JavaScript .
¿Cómo se ve la factura PDF generada?

¿Cómo transmitir un PDF directamente al navegador sin un cuadro de diálogo de descarga?
Para servir un PDF en línea (abrirlo en el visor integrado del navegador en lugar de descargarlo) se requieren dos pequeños cambios: establecer Content-Disposition en inline y omitir el nombre del archivo de la llamada File().
[HttpPost("report/preview")]
public async Task<IActionResult> PreviewReport([FromBody] ReportRequest request)
{
string html = BuildReportHtml(request);
var pdfDocument = await _renderer.RenderHtmlAsPdfAsync(html);
// "inline" tells the browser to display rather than download.
Response.Headers["Content-Disposition"] = "inline; filename=report.pdf";
return new FileContentResult(pdfDocument.BinaryData, "application/pdf");
}
[HttpPost("report/preview")]
public async Task<IActionResult> PreviewReport([FromBody] ReportRequest request)
{
string html = BuildReportHtml(request);
var pdfDocument = await _renderer.RenderHtmlAsPdfAsync(html);
// "inline" tells the browser to display rather than download.
Response.Headers["Content-Disposition"] = "inline; filename=report.pdf";
return new FileContentResult(pdfDocument.BinaryData, "application/pdf");
}
Imports Microsoft.AspNetCore.Mvc
<HttpPost("report/preview")>
Public Async Function PreviewReport(<FromBody> request As ReportRequest) As Task(Of IActionResult)
Dim html As String = BuildReportHtml(request)
Dim pdfDocument = Await _renderer.RenderHtmlAsPdfAsync(html)
' "inline" tells the browser to display rather than download.
Response.Headers("Content-Disposition") = "inline; filename=report.pdf"
Return New FileContentResult(pdfDocument.BinaryData, "application/pdf")
End Function
Se recomienda usar la sobrecarga asíncrona RenderHtmlAsPdfAsync para los controladores ASP.NET Core porque libera el subproceso del grupo de subprocesos mientras Chromium realiza la representación, manteniendo el servidor en capacidad de respuesta bajo carga concurrente.
¿Cómo funciona la generación de PDF basada en memoria?

La matriz de bytes pdfDocument.BinaryData reside íntegramente en la memoria administrada. No hay ninguna ruta de archivo intermedia involucrada. El encabezado Content-Disposition controla si el PDF se muestra en línea o se ofrece como descarga, un comportamiento del navegador definido por la especificación HTTP. Para obtener una visión más profunda del enfoque MemoryStream, incluida la transmisión a Azure Blob Storage, visita la documentación de transmisión de memoria en PDF .
¿Cómo generar archivos PDF a partir de los resultados de consultas de Entity Framework Core?
La mayoría de las aplicaciones empresariales extraen datos de informes de una base de datos en lugar de generarlos en el momento de la llamada. El siguiente patrón consulta Entity Framework Core , genera una tabla HTML y devuelve un PDF, todo ello con una única acción del controlador.
[HttpGet("report/monthly")]
public async Task<IActionResult> MonthlyReport(int year, int month)
{
// Pull aggregated transaction data from EF Core.
var rows = await _dbContext.Transactions
.Where(t => t.Date.Year == year && t.Date.Month == month)
.GroupBy(t => t.Category)
.Select(g => new { Category = g.Key, Count = g.Count(), Total = g.Sum(t => t.Amount) })
.OrderByDescending(g => g.Total)
.ToListAsync();
string tableRows = string.Join("", rows.Select(r =>
$"<tr><td>{r.Category}</td><td>{r.Count}</td><td>${r.Total:F2}</td></tr>"));
string html = $"""
<html><body style="font-family:Arial,sans-serif;padding:32px">
<h1>Monthly Report -- {month:D2}/{year}</h1>
<table style="width:100%;border-collapse:collapse">
<thead>
<tr style="background:#e5e7eb">
<th style="padding:8px;border:1px solid #d1d5db">Category</th>
<th style="padding:8px;border:1px solid #d1d5db">Transactions</th>
<th style="padding:8px;border:1px solid #d1d5db">Total</th>
</tr>
</thead>
<tbody>{tableRows}</tbody>
</table>
</body></html>
""";
var pdf = _renderer.RenderHtmlAsPdf(html);
pdf.MetaData.Title = $"Monthly Report {month:D2}/{year}";
pdf.MetaData.Author = "Reporting System";
return File(pdf.BinaryData, "application/pdf", $"report-{year}-{month:D2}.pdf");
}
[HttpGet("report/monthly")]
public async Task<IActionResult> MonthlyReport(int year, int month)
{
// Pull aggregated transaction data from EF Core.
var rows = await _dbContext.Transactions
.Where(t => t.Date.Year == year && t.Date.Month == month)
.GroupBy(t => t.Category)
.Select(g => new { Category = g.Key, Count = g.Count(), Total = g.Sum(t => t.Amount) })
.OrderByDescending(g => g.Total)
.ToListAsync();
string tableRows = string.Join("", rows.Select(r =>
$"<tr><td>{r.Category}</td><td>{r.Count}</td><td>${r.Total:F2}</td></tr>"));
string html = $"""
<html><body style="font-family:Arial,sans-serif;padding:32px">
<h1>Monthly Report -- {month:D2}/{year}</h1>
<table style="width:100%;border-collapse:collapse">
<thead>
<tr style="background:#e5e7eb">
<th style="padding:8px;border:1px solid #d1d5db">Category</th>
<th style="padding:8px;border:1px solid #d1d5db">Transactions</th>
<th style="padding:8px;border:1px solid #d1d5db">Total</th>
</tr>
</thead>
<tbody>{tableRows}</tbody>
</table>
</body></html>
""";
var pdf = _renderer.RenderHtmlAsPdf(html);
pdf.MetaData.Title = $"Monthly Report {month:D2}/{year}";
pdf.MetaData.Author = "Reporting System";
return File(pdf.BinaryData, "application/pdf", $"report-{year}-{month:D2}.pdf");
}
Imports Microsoft.AspNetCore.Mvc
Imports System.Threading.Tasks
Imports System.Linq
<HttpGet("report/monthly")>
Public Async Function MonthlyReport(year As Integer, month As Integer) As Task(Of IActionResult)
' Pull aggregated transaction data from EF Core.
Dim rows = Await _dbContext.Transactions _
.Where(Function(t) t.Date.Year = year AndAlso t.Date.Month = month) _
.GroupBy(Function(t) t.Category) _
.Select(Function(g) New With {Key .Category = g.Key, Key .Count = g.Count(), Key .Total = g.Sum(Function(t) t.Amount)}) _
.OrderByDescending(Function(g) g.Total) _
.ToListAsync()
Dim tableRows As String = String.Join("", rows.Select(Function(r) $"<tr><td>{r.Category}</td><td>{r.Count}</td><td>${r.Total:F2}</td></tr>"))
Dim html As String = $"
<html><body style='font-family:Arial,sans-serif;padding:32px'>
<h1>Monthly Report -- {month:D2}/{year}</h1>
<table style='width:100%;border-collapse:collapse'>
<thead>
<tr style='background:#e5e7eb'>
<th style='padding:8px;border:1px solid #d1d5db'>Category</th>
<th style='padding:8px;border:1px solid #d1d5db'>Transactions</th>
<th style='padding:8px;border:1px solid #d1d5db'>Total</th>
</tr>
</thead>
<tbody>{tableRows}</tbody>
</table>
</body></html>
"
Dim pdf = _renderer.RenderHtmlAsPdf(html)
pdf.MetaData.Title = $"Monthly Report {month:D2}/{year}"
pdf.MetaData.Author = "Reporting System"
Return File(pdf.BinaryData, "application/pdf", $"report-{year}-{month:D2}.pdf")
End Function
La configuración de pdf.MetaData.Title y pdf.MetaData.Author incorpora esa información en las propiedades del documento PDF, lo que resulta útil para el seguimiento del cumplimiento y los sistemas de gestión de documentos. Para diseños de informes más sofisticados, considere estilos de impresión CSS , saltos de página explícitos e imágenes de gráficos incrustadas .
¿Cómo aplicar encabezados, pies de página y seguridad a los PDF generados?
Los documentos de producción a menudo requieren encabezados con el título del documento, pies de página con números de página y controles de acceso que eviten la impresión o copia no autorizadas. El ChromePdfRenderOptions de IronPDF cubre todos estos requisitos.
[HttpPost("document/secured")]
public async Task<IActionResult> GenerateSecuredDocument([FromBody] SecuredDocRequest request)
{
var renderOptions = new ChromePdfRenderOptions
{
PaperSize = PdfPaperSize.A4,
MarginTop = 45,
MarginBottom = 45,
MarginLeft = 25,
MarginRight = 25,
EnableJavaScript = true,
WaitFor = new WaitFor { RenderDelay = 500 }
};
renderOptions.TextHeader = new TextHeaderFooter
{
CenterText = request.DocumentTitle,
DrawDividerLine = true,
FontSize = 11
};
renderOptions.TextFooter = new TextHeaderFooter
{
LeftText = "{date} {time}",
RightText = "Page {page} of {total-pages}",
FontSize = 9
};
_renderer.RenderingOptions = renderOptions;
var pdf = await _renderer.RenderHtmlAsPdfAsync(request.HtmlContent);
if (request.RequirePassword)
{
pdf.SecuritySettings.OwnerPassword = request.OwnerPassword;
pdf.SecuritySettings.UserPassword = request.UserPassword;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
}
return File(pdf.BinaryData, "application/pdf", $"{request.FileName}.pdf");
}
[HttpPost("document/secured")]
public async Task<IActionResult> GenerateSecuredDocument([FromBody] SecuredDocRequest request)
{
var renderOptions = new ChromePdfRenderOptions
{
PaperSize = PdfPaperSize.A4,
MarginTop = 45,
MarginBottom = 45,
MarginLeft = 25,
MarginRight = 25,
EnableJavaScript = true,
WaitFor = new WaitFor { RenderDelay = 500 }
};
renderOptions.TextHeader = new TextHeaderFooter
{
CenterText = request.DocumentTitle,
DrawDividerLine = true,
FontSize = 11
};
renderOptions.TextFooter = new TextHeaderFooter
{
LeftText = "{date} {time}",
RightText = "Page {page} of {total-pages}",
FontSize = 9
};
_renderer.RenderingOptions = renderOptions;
var pdf = await _renderer.RenderHtmlAsPdfAsync(request.HtmlContent);
if (request.RequirePassword)
{
pdf.SecuritySettings.OwnerPassword = request.OwnerPassword;
pdf.SecuritySettings.UserPassword = request.UserPassword;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
}
return File(pdf.BinaryData, "application/pdf", $"{request.FileName}.pdf");
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc
<HttpPost("document/secured")>
Public Async Function GenerateSecuredDocument(<FromBody> request As SecuredDocRequest) As Task(Of IActionResult)
Dim renderOptions As New ChromePdfRenderOptions With {
.PaperSize = PdfPaperSize.A4,
.MarginTop = 45,
.MarginBottom = 45,
.MarginLeft = 25,
.MarginRight = 25,
.EnableJavaScript = True,
.WaitFor = New WaitFor With {.RenderDelay = 500}
}
renderOptions.TextHeader = New TextHeaderFooter With {
.CenterText = request.DocumentTitle,
.DrawDividerLine = True,
.FontSize = 11
}
renderOptions.TextFooter = New TextHeaderFooter With {
.LeftText = "{date} {time}",
.RightText = "Page {page} of {total-pages}",
.FontSize = 9
}
_renderer.RenderingOptions = renderOptions
Dim pdf = Await _renderer.RenderHtmlAsPdfAsync(request.HtmlContent)
If request.RequirePassword Then
pdf.SecuritySettings.OwnerPassword = request.OwnerPassword
pdf.SecuritySettings.UserPassword = request.UserPassword
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
pdf.SecuritySettings.AllowUserCopyPasteContent = False
End If
Return File(pdf.BinaryData, "application/pdf", $"{request.FileName}.pdf")
End Function
La configuración WaitFor.RenderDelay es particularmente útil cuando su HTML incluye bibliotecas de gráficos como Chart.js o ApexCharts que terminan de dibujar de forma asincrónica. Establecer un retraso de 300 a 500 ms garantiza que Chromium capture el estado renderizado final. Para los documentos que necesitan cumplir con los estándares de archivo, combine el enfoque anterior con el cumplimiento de PDF/A y las firmas digitales .
IronPDF resuelve automáticamente los tokens {page} y {total-pages} del texto del pie de página durante el renderizado. Las opciones adicionales para encabezados y pies de página incluyen encabezados HTML para la colocación del logotipo y funciones de anulación por sección.
¿Qué opciones de renderizado están disponibles?
La siguiente tabla resume las propiedades ChromePdfRenderOptions más útiles para la generación sobre la marcha:
| Propiedad | Tipo | Objetivo |
|---|---|---|
| PaperSize | PdfPaperSize | Establece las dimensiones de la página (A4, Carta, Legal, personalizada) |
| MarginTop / MarginBottom | int (mm) | Controla el espaciado del área imprimible |
| EnableJavaScript | bool | Permite la ejecución de JS antes de la captura |
| WaitFor.RenderDelay | int (ms) | Retrasa la captura para la representación asincrónica |
| TextHeader / TextFooter | TextHeaderFooter | Encabezados y pies de página en ejecución |
| HtmlHeader / HtmlFooter | HtmlHeaderFooter | Encabezados y pies de página con formato HTML y con imágenes |
| GrayScale | bool | Produce PDF monocromo |
| FitToPaperWidth | bool | Ajusta el contenido ancho a la página |
¿Cuáles son las mejores prácticas de rendimiento para la generación de PDF de gran volumen?
Cuando un solo servidor maneja cientos de solicitudes de PDF simultáneas, unas pocas decisiones arquitectónicas tienen un impacto enorme en el rendimiento y la latencia.
Registro del renderizador singleton. Como se muestra en la sección de instalación, registrar ChromePdfRenderer como singleton en el contenedor DI evita el coste de iniciar un nuevo subproceso de Chromium por solicitud. Según la guía de rendimiento de ASP.NET Core de Microsoft , minimizar la asignación de objetos y reutilizar recursos costosos son las dos optimizaciones más efectivas disponibles.
Utilice siempre async. RenderHtmlAsPdfAsync devuelve un Task<PdfDocument> y suspende el hilo del controlador mientras Chromium funciona. Esto libera el grupo de subprocesos para manejar otras solicitudes entrantes en paralelo, por lo que la documentación asíncrona recomienda esta sobrecarga para los hosts web. La sobrecarga sincrónica solo es apropiada para herramientas de consola o servicios en segundo plano donde el bloqueo de subprocesos es aceptable.
Transmita directamente, omita la matriz intermedia siempre que sea posible. Para archivos PDF grandes, .Stream se puede escribir directamente en el cuerpo de la respuesta sin materializar la matriz de bytes completa:
[HttpGet("document/large")]
public IActionResult StreamLargeDocument(int documentId)
{
string html = BuildLargeDocumentHtml(documentId);
var pdf = _renderer.RenderHtmlAsPdf(html);
// Stream.Position is already at 0; no seek needed.
return File(pdf.Stream, "application/pdf", $"document-{documentId}.pdf");
}
[HttpGet("document/large")]
public IActionResult StreamLargeDocument(int documentId)
{
string html = BuildLargeDocumentHtml(documentId);
var pdf = _renderer.RenderHtmlAsPdf(html);
// Stream.Position is already at 0; no seek needed.
return File(pdf.Stream, "application/pdf", $"document-{documentId}.pdf");
}
Imports Microsoft.AspNetCore.Mvc
<HttpGet("document/large")>
Public Function StreamLargeDocument(documentId As Integer) As IActionResult
Dim html As String = BuildLargeDocumentHtml(documentId)
Dim pdf = _renderer.RenderHtmlAsPdf(html)
' Stream.Position is already at 0; no seek needed.
Return File(pdf.Stream, "application/pdf", $"document-{documentId}.pdf")
End Function
Desechar después de usar. PdfDocument implementa IDisposable. Al envolverlo en una declaración using se libera rápidamente el búfer de memoria subyacente, lo que es importante cuando se generan muchos PDF grandes uno tras otro:
using var pdf = _renderer.RenderHtmlAsPdf(html);
byte[] data = pdf.BinaryData;
// pdf is disposed here; data is safely copied to the local array.
return File(data, "application/pdf", "output.pdf");
using var pdf = _renderer.RenderHtmlAsPdf(html);
byte[] data = pdf.BinaryData;
// pdf is disposed here; data is safely copied to the local array.
return File(data, "application/pdf", "output.pdf");
Imports System.IO
Using pdf = _renderer.RenderHtmlAsPdf(html)
Dim data As Byte() = pdf.BinaryData
' pdf is disposed here; data is safely copied to the local array.
Return File(data, "application/pdf", "output.pdf")
End Using
Para obtener orientación sobre la implementación de la nube que cubre entornos de Azure , AWS, Docker y Linux, la documentación de IronPDF proporciona notas de configuración específicas del entorno. Si la primera renderización después del inicio es lenta, consulte la guía de calentamiento y almacenamiento en caché para conocer estrategias para preinicializar el renderizador antes de que llegue la primera solicitud del usuario.
¿Cómo agregar una marca de agua a un PDF generado?
Se puede agregar una marca de agua de texto o imagen a cada página del documento generado antes de la transmisión:
[HttpGet("document/draft/{id:int}")]
public IActionResult GetDraftDocument(int id)
{
string html = BuildDocumentHtml(id);
var pdf = _renderer.RenderHtmlAsPdf(html);
// Stamp "DRAFT" diagonally across every page.
pdf.ApplyWatermark(
"<h1 style='color:rgba(200,0,0,0.25);transform:rotate(-45deg)'>DRAFT</h1>",
rotation: 45,
opacity: 30
);
return File(pdf.BinaryData, "application/pdf", $"draft-{id}.pdf");
}
[HttpGet("document/draft/{id:int}")]
public IActionResult GetDraftDocument(int id)
{
string html = BuildDocumentHtml(id);
var pdf = _renderer.RenderHtmlAsPdf(html);
// Stamp "DRAFT" diagonally across every page.
pdf.ApplyWatermark(
"<h1 style='color:rgba(200,0,0,0.25);transform:rotate(-45deg)'>DRAFT</h1>",
rotation: 45,
opacity: 30
);
return File(pdf.BinaryData, "application/pdf", $"draft-{id}.pdf");
}
<AttributeUsage(AttributeTargets.Method, Inherited:=True, AllowMultiple:=False)>
Public Class HttpGetAttribute
Inherits Attribute
Public Sub New(route As String)
End Sub
End Class
<HttpGet("document/draft/{id:int}")>
Public Function GetDraftDocument(id As Integer) As IActionResult
Dim html As String = BuildDocumentHtml(id)
Dim pdf = _renderer.RenderHtmlAsPdf(html)
' Stamp "DRAFT" diagonally across every page.
pdf.ApplyWatermark(
"<h1 style='color:rgba(200,0,0,0.25);transform:rotate(-45deg)'>DRAFT</h1>",
rotation:=45,
opacity:=30
)
Return File(pdf.BinaryData, "application/pdf", $"draft-{id}.pdf")
End Function
Para conocer las opciones de configuración completas de marcas de agua, incluidas las marcas de agua de imágenes y el control por página, consulte la documentación de marcas de agua .
¿Cuales son tus próximos pasos?
La generación dinámica de PDF en ASP.NET Core sigue un patrón consistente: crea tu HTML, llama a RenderHtmlAsPdf o su sobrecarga asíncrona y devuelve el resultado a través de un FileResult. IronPDF maneja todo lo intermedio (representación de Chromium, aplicación CSS, ejecución de JavaScript ) sin requerir E/S de disco en ninguna etapa.
Desde aquí, puede explorar varias direcciones dependiendo de los requisitos de su aplicación. Si sus PDF necesitan combinar varios documentos de origen, la guía de combinación y división cubre cómo unir PDF existentes con páginas recién renderizadas. Si necesita que los usuarios completen y envíen formularios integrados en un PDF, la documentación de formularios interactivos muestra cómo crear y leer valores de campo. Para las industrias reguladas, la conformidad con PDF/A y la accesibilidad con PDF/UA garantizan que los documentos cumplan con los estándares de archivo y accesibilidad.
Si está evaluando IronPDF frente a otras alternativas, la comparación iText vs IronPDF proporciona un desglose técnico lado a lado. Cuando esté listo para pasar a producción, compre una licencia para desbloquear todas las funciones y obtener acceso a soporte de ingeniería prioritario. La referencia completa de la API documenta cada clase y método analizado en esta guía.
Si tiene alguna pregunta o problema durante la implementación, el equipo de soporte de ingeniería está disponible para ayudarle. Para obtener información específica sobre Blazor Server o MAUI, existen guías específicas que explican las diferencias de configuración para cada modelo de host.
Preguntas Frecuentes
¿Cómo puedo generar PDFs dinámicamente en ASP.NET Core?
Puedes usar IronPDF para generar PDFs dinámicamente en ASP.NET Core sin guardar archivos en el disco. Te permite transmitir PDFs directamente a los navegadores.
¿Cuáles son los beneficios de usar IronPDF para la generación de PDF?
IronPDF proporciona un potente motor de renderizado que permite la creación dinámica de PDFs directamente dentro de tus proyectos .NET Core, asegurando generación instantánea de PDFs sin necesidad de almacenamiento en el servidor.
¿Puede IronPDF usarse para crear facturas e informes?
Sí, IronPDF es adecuado para crear varios tipos de documentos como facturas, informes y certificados, todos generados sobre la marcha en aplicaciones ASP.NET Core.
¿Es necesario el almacenamiento en el servidor al usar IronPDF?
No, IronPDF te permite generar y transmitir PDFs directamente a los navegadores sin necesidad de almacenamiento en el servidor, haciéndolo eficiente y rápido.
¿Qué tipo de aplicaciones pueden beneficiarse de la generación de PDFs sobre la marcha?
Las aplicaciones web modernas, en particular aquellas que requieren creación de documentos en tiempo real como sistemas de facturación y herramientas de informes, pueden beneficiarse en gran medida de la generación de PDFs sobre la marcha proporcionada por IronPDF.
¿IronPDF es compatible con proyectos .NET Core?
Sí, IronPDF es completamente compatible con proyectos .NET Core, permitiendo a los desarrolladores integrar capacidades de generación de PDFs sin problemas en sus aplicaciones.


