Cómo crear un servicio centralizado de generación de PDF con ASP.NET Core y IronPDF
Cree una API de PDF .NET lista para producción usando ASP.NET Core e IronPDF para centralizar la lógica de generación de PDF, lo que permite la creación consistente de documentos en todas sus aplicaciones con puntos finales RESTful para conversión de HTML a PDF, fusión, marca de agua y procesamiento dinámico de plantillas.
Al trabajar con aplicaciones modernas, los desarrolladores .NET suelen necesitar crear un servicio centralizado de generación de PDF. Ya sea que generen facturas, informes, certificados o contratos, contar con una API .NET PDF dedicada mejora su flujo de trabajo de generación de PDF. ¿Cómo ayuda? Proporciona consistencia, facilidad de mantenimiento y escalabilidad en tus aplicaciones de escritorio y web. Administrar el contenido de documentos, páginas PDF y campos de formularios PDF se vuelve sencillo.
En este tutorial, aprenderá a crear una API PDF lista para producción utilizando ASP.NET Core e IronPDF, una potente biblioteca PDF .NET. Crearemos puntos finales RESTful que generarán archivos PDF a partir de HTML, fusionarán documentos , agregarán marcas de agua y manejarán varios escenarios de PDF del mundo real en su API web.
¿Por qué crear una API PDF dedicada?
Antes de sumergirnos en el código, entendamos por qué tiene sentido crear una API dedicada de PDF:
- Lógica centralizada : toda la lógica de generación de PDF reside en un solo lugar, lo que simplifica el mantenimiento y las actualizaciones.
- Arquitectura de microservicios : perfecta para arquitecturas orientadas a servicios donde diferentes aplicaciones necesitan capacidades de PDF.
- Optimización del rendimiento : es más fácil escalar y optimizar un servicio dedicado para archivos PDF grandes, páginas múltiples y datos dinámicos mediante operaciones asincrónicas y técnicas de rendimiento .
- Agnóstico del lenguaje : cualquier aplicación cliente puede consumir la API independientemente del lenguaje de programación.
- Salida consistente : garantiza que todos los archivos PDF de su organización mantengan un diseño, formato y contenido consistentes.
¿Listo para empezar a construir? Descargue la prueba gratuita de IronPDF y siga este tutorial para crear archivos PDF programáticamente en sus proyectos de .NET Framework.
¿Qué hace que IronPDF sea la biblioteca PDF .NET completa?
IronPDF destaca como la principal biblioteca PDF para desarrolladores .NET, ya que ofrece un completo conjunto de funciones que hacen que la generación de PDF en proyectos de API web sea sencilla y fiable. Construido sobre un motor de renderizado Chrome , garantiza conversiones de HTML a PDF con píxeles perfectos en solo unas pocas líneas de código mientras mantiene todo el estilo, la ejecución de JavaScript y los diseños responsivos .
Las capacidades clave que hacen que IronPDF sea ideal para el desarrollo de API de PDF para .NET:
- Representación basada en Chrome : utiliza el motor de Google Chrome para una conversión precisa de HTML a PDF con soporte completo para imágenes incrustadas y activos web.
- Amplio conjunto de funciones : edite documentos con firmas digitales , formularios PDF , anotaciones , cifrado , compresión y más.
- Cree archivos PDF seguros : administre contenido confidencial con cifrado , firmas digitales y protección de documentos.
- Múltiples formatos de entrada : utilice HTML, URL, imágenes y documentos de Office para crear archivos PDF.
- Manipulación avanzada : fusione páginas , divida documentos , aplique marcas de agua , cree formularios interactivos y manipule archivos PDF mediante programación.
- Compatibilidad multiplataforma : funciona en Windows , Linux , macOS , Docker y plataformas en la nube .
- Rendimiento optimizado : operaciones asincrónicas , gestión de memoria eficiente y renderizado rápido con opciones de retraso de renderizado .
¿Cómo configurar su proyecto de API de documentos PDF?
Comencemos creando un nuevo proyecto API web de ASP.NET Core e instalando los paquetes necesarios.
¿Cuáles son los requisitos previos?
- SDK de .NET 6.0 o posterior
- Visual Studio 2022 or Visual Studio Code
- Postman o una herramienta de prueba de API similar para probar su API REST de PDF
¿Cómo creo el proyecto?
Primero, creemos el proyecto donde construiremos nuestra herramienta de generación de PDF.
dotnet new webapi -n PdfApiService
cd PdfApiServicedotnet new webapi -n PdfApiService
cd PdfApiService¿Cómo instalo IronPDF?
A continuación, agregue IronPDF a su proyecto a través de NuGet:
dotnet add package IronPDFdotnet add package IronPDFO, utilizando el Consola del Administrador de Paquetes de NuGet en Visual Studio:
Install-Package IronPDFPara conocer opciones de instalación avanzadas, incluidos paquetes específicos de la plataforma , configuración de Docker o configuraciones de Linux , consulte la documentación de instalación de IronPDF .
¿Qué estructura de proyecto debo utilizar?
Un buen desarrollo de C# requiere mantener una carpeta de proyecto limpia y bien estructurada. Por ejemplo:
¿Cómo crear su primer punto final PDF?
Construyamos un endpoint simple que convierta HTML al formato PDF. Primero, cree la interfaz del servicio y la implementación:
¿Cómo creo el servicio PDF?
Primero, agregue lo siguiente a su archivo IPdfService.cs :
public interface IPdfService
{
byte[] GeneratePdfFromHtml(string htmlContent);
byte[] GeneratePdfFromUrl(string url);
}public interface IPdfService
{
byte[] GeneratePdfFromHtml(string htmlContent);
byte[] GeneratePdfFromUrl(string url);
}En el archivo PdfService.cs , agregue esto:
using IronPdf;
public class PdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public PdfService()
{
_renderer = new ChromePdfRenderer();
// Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20;
_renderer.RenderingOptions.MarginBottom = 20;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GeneratePdfFromHtml(string htmlContent)
{
// Generate PDF from HTML using the .NET PDF API
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
}
public byte[] GeneratePdfFromUrl(string url)
{
// Convert URL to PDF in the REST API
var pdf = _renderer.RenderUrlAsPdf(url);
return pdf.BinaryData;
}
}using IronPdf;
public class PdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public PdfService()
{
_renderer = new ChromePdfRenderer();
// Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20;
_renderer.RenderingOptions.MarginBottom = 20;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GeneratePdfFromHtml(string htmlContent)
{
// Generate PDF from HTML using the .NET PDF API
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
}
public byte[] GeneratePdfFromUrl(string url)
{
// Convert URL to PDF in the REST API
var pdf = _renderer.RenderUrlAsPdf(url);
return pdf.BinaryData;
}
}PdfService se encarga de convertir HTML a PDF. Al utilizar ChromePdfRenderer de IronPDF, esta clase configura valores predeterminados como márgenes de página y representación de fondo para obtener resultados profesionales. Para configuraciones de renderizado avanzadas, explore las opciones de renderizado de IronPDF .
Cuando el controlador pasa HTML sin procesar, el servicio lo convierte en un PDF de alta calidad y devuelve los datos de bytes para descargar. También convierte páginas web enteras directamente en archivos PDF mediante la conversión de URL a PDF .
¿Cómo creo el controlador?
Ahora crea el controlador para tu API. Esto proporciona un punto final que genera archivos PDF a partir de HTML y le permite descargar y guardar documentos PDF en su sistema.
// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IPdfService _pdfService;
public PdfController(IPdfService pdfService)
{
_pdfService = pdfService;
}
[HttpPost("html-to-pdf")]
public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
{
try
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
// Return as downloadable file
return File(pdfBytes, "application/pdf", "document.pdf");
}
catch (Exception ex)
{
return BadRequest($"Error generating PDF: {ex.Message}");
}
}
}// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IPdfService _pdfService;
public PdfController(IPdfService pdfService)
{
_pdfService = pdfService;
}
[HttpPost("html-to-pdf")]
public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
{
try
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
// Return as downloadable file
return File(pdfBytes, "application/pdf", "document.pdf");
}
catch (Exception ex)
{
return BadRequest($"Error generating PDF: {ex.Message}");
}
}
}Luego, en el archivo HtmlRequest.cs , agregue esto:
// Models/HtmlRequest.cs
public class HtmlRequest
{
public string HtmlContent { get; set; }
public string FileName { get; set; } = "document.pdf";
}// Models/HtmlRequest.cs
public class HtmlRequest
{
public string HtmlContent { get; set; }
public string FileName { get; set; } = "document.pdf";
}Esto configura un punto final de API que convierte HTML en un PDF descargable. Cuando alguien envía HTML a api/pdf/html-to-pdf , PdfController delega la conversión al servicio.
Una vez creado, el controlador devuelve el PDF como archivo descargable. La solicitud utiliza el modelo HtmlRequest , que contiene el HTML y un nombre de archivo opcional. Esto hace que sea fácil para los clientes enviar HTML y recibir un PDF pulido.
¿Cómo registro servicios?
Actualice su Program.cs para registrar el servicio PDF:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();¿Cómo manejar diferentes tipos de respuesta?
Su API debería soportar diferentes formas de devolver PDFs en función de las necesidades del cliente:
[HttpPost("generate")]
public IActionResult GeneratePdf([FromBody] PdfRequest request)
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
switch (request.ResponseType?.ToLower())
{
case "base64":
return Ok(new
{
data = Convert.ToBase64String(pdfBytes),
filename = request.FileName
});
case "inline":
return File(pdfBytes, "application/pdf");
default: // download
return File(pdfBytes, "application/pdf", request.FileName);
}
}[HttpPost("generate")]
public IActionResult GeneratePdf([FromBody] PdfRequest request)
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
switch (request.ResponseType?.ToLower())
{
case "base64":
return Ok(new
{
data = Convert.ToBase64String(pdfBytes),
filename = request.FileName
});
case "inline":
return File(pdfBytes, "application/pdf");
default: // download
return File(pdfBytes, "application/pdf", request.FileName);
}
}Esto agrega un punto final de generación de PDF flexible. En lugar de forzar las descargas, el método GeneratePdf permite a los clientes elegir cómo reciben los resultados: como descarga, en línea en el navegador o codificados en Base64 para uso de API.
El modelo PdfRequest extiende HtmlRequest con una opción ResponseType . Esto permite a los usuarios controlar la entrega de PDF, lo que aumenta la versatilidad de la API. Para gestionar archivos PDF en memoria sin acceso al sistema de archivos, consulte la documentación de flujo de memoria de IronPDF .
Cuando ejecutamos nuestro programa, veremos esta salida en Swagger:
¿Cómo implementar operaciones PDF comunes?
Ampliemos nuestro servicio para manejar varios escenarios de generación de PDF:
¿Cómo convierto URL a PDF?
[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
try
{
var pdfBytes = await Task.Run(() =>
_pdfService.GeneratePdfFromUrl(request.Url));
return File(pdfBytes, "application/pdf",
$"{request.FileName ?? "website"}.pdf");
}
catch (Exception ex)
{
return BadRequest($"Failed to convert URL: {ex.Message}");
}
}
public class UrlRequest
{
public string Url { get; set; }
public string FileName { get; set; }
}[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
try
{
var pdfBytes = await Task.Run(() =>
_pdfService.GeneratePdfFromUrl(request.Url));
return File(pdfBytes, "application/pdf",
$"{request.FileName ?? "website"}.pdf");
}
catch (Exception ex)
{
return BadRequest($"Failed to convert URL: {ex.Message}");
}
}
public class UrlRequest
{
public string Url { get; set; }
public string FileName { get; set; }
}Este punto final convierte las URL en archivos PDF descargables. Cuando una solicitud POST llega a /api/pdf/url-to-pdf , el controlador usa _pdfService para convertir la URL en bytes PDF en segundo plano y luego los devuelve para su descarga. Si la conversión falla, responde con un mensaje de error claro. Para sitios web con autenticación, consulte la documentación de inicio de sesión de IronPDF .
Intentemos usar la URL "https://www.apple.com/nz " y probamos la solicitud POST. A continuación, el resultado que obtuvimos:
¿Qué aspecto tiene el resultado?
¿Cómo agrego marcas de agua personalizadas?
public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
// Load PDF directly from file
var pdf = PdfDocument.FromFile(filePath);
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
);
return pdf.BinaryData;
}public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
// Load PDF directly from file
var pdf = PdfDocument.FromFile(filePath);
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
);
return pdf.BinaryData;
}Esto carga manualmente un archivo local para realizar pruebas. Puede ajustar esto para que su API de PDF genere un PDF y luego aplique marcas de agua personalizadas fácilmente. Para conocer opciones avanzadas de marca de agua, incluidas marcas de agua de imágenes y posicionamiento personalizado, consulte la guía de marca de agua .
¿Cómo se ve la salida de la marca de agua?
¿Cómo agregar datos dinámicos con plantillas?
Para aplicaciones del mundo real, a menudo necesitará generar PDFs a partir de plantillas con datos dinámicos:
[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
// Simple template replacement
var html = request.Template;
foreach (var item in request.Data)
{
html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
}
var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
public string Template { get; set; }
public Dictionary<string, string> Data { get; set; }
public string FileName { get; set; } = "document.pdf";
}[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
// Simple template replacement
var html = request.Template;
foreach (var item in request.Data)
{
html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
}
var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
public string Template { get; set; }
public Dictionary<string, string> Data { get; set; }
public string FileName { get; set; } = "document.pdf";
}Para escenarios de plantillas avanzados con Razor, Handlebars u otros motores, consulte la documentación de HTML a PDF de IronPDF . También puede explorar la conversión de CSHTML a PDF para aplicaciones MVC y Razor a PDF para aplicaciones Blazor. Para la representación sin interfaz gráfica de Razor, consulte la guía CSHTML sin interfaz gráfica .
¿Cómo optimizar el rendimiento?
Al construir una API de PDF de producción, el rendimiento es crucial. Aquí hay estrategias clave de optimización:
¿Por qué utilizar operaciones asincrónicas?
Utilice codificación asincrónica cuando sus proyectos involucren operaciones de E/S. Esto ayuda especialmente cuando el contenido PDF proviene de recursos externos como:
- Descarga de páginas HTML (
RenderUrlAsPdf) - Recuperando imágenes, CSS o fuentes a través de HTTP
- Leyendo/escribiendo archivos en disco o almacenamiento en la nube
Estas operaciones pueden bloquear subprocesos, pero async evita que los subprocesos de API permanezcan inactivos. Para conocer patrones completos de generación de PDF asincrónicos, consulte la guía de generación de PDF asincrónicos .
Ejemplo:
public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
return await Task.Run(() =>
{
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
});
}public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
return await Task.Run(() =>
{
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
});
}Para escenarios de generación de PDF en paralelo, explore técnicas de procesamiento paralelo y de subprocesos múltiples .
¿Qué opciones de renderizado debo configurar?
Configure IronPDF para un rendimiento óptimo:
_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeout_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeoutPara obtener opciones de configuración de renderizado completas, incluidas las configuraciones de la ventana gráfica , los tamaños de papel personalizados y la orientación de la página , consulte la documentación de opciones de renderizado .
¿Cómo proteger su API PDF?
La seguridad es esencial para cualquier API de producción. Aquí hay un enfoque simple de autenticación con clave API:
// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string ApiKeyHeader = "X-API-Key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("API Key required");
return;
}
// Validate API key (in production, check against database)
var validApiKey = context.RequestServices
.GetRequiredService<IConfiguration>()["ApiKey"];
if (apiKey != validApiKey)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Invalid API Key");
return;
}
await _next(context);
}
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string ApiKeyHeader = "X-API-Key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("API Key required");
return;
}
// Validate API key (in production, check against database)
var validApiKey = context.RequestServices
.GetRequiredService<IConfiguration>()["ApiKey"];
if (apiKey != validApiKey)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Invalid API Key");
return;
}
await _next(context);
}
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();Para escenarios de autenticación avanzada, considere:
- Autenticación JWT - Estándar de la industria para autenticación de API
- OAuth 2.0 - Para integraciones de terceros
- Integración AD de Azure - Autenticación empresarial
- Limitación de Tasa API - Prevenir abusos y garantizar un uso justo
- Encabezados HTTP : configuración de encabezados personalizados para mayor seguridad
Para la seguridad específica de PDF, implemente protección con contraseña , firmas digitales y desinfección de PDF para eliminar contenido potencialmente malicioso.
¿Cómo crear una API de generación de facturas en el mundo real?
Construyamos un punto final de generación de facturas práctico que demuestre una implementación completa. Este ejemplo muestra cómo una API de PDF .NET de producción genera facturas profesionales con datos dinámicos.
Primero, crea un nuevo archivo en tu carpeta Modelos. En este caso, he llamado al mío Factura.cs. Luego agrega el siguiente código:
public class Invoice
{
public string InvoiceNumber { get; set; }
public DateTime Date { get; set; }
public string CustomerName { get; set; }
public string CustomerAddress { get; set; }
public List<InvoiceItem> Items { get; set; }
public decimal Tax { get; set; }
}
public class InvoiceItem
{
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Total => Quantity * UnitPrice;
}public class Invoice
{
public string InvoiceNumber { get; set; }
public DateTime Date { get; set; }
public string CustomerName { get; set; }
public string CustomerAddress { get; set; }
public List<InvoiceItem> Items { get; set; }
public decimal Tax { get; set; }
}
public class InvoiceItem
{
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Total => Quantity * UnitPrice;
}A continuación, cree un nuevo archivo de servicio para el generador de facturas. En su carpeta de Servicios, añada el siguiente código. Creé un archivo llamado InvoiceService.cs . Este código maneja el estilo y el diseño de su factura PDF:
public class InvoiceService
{
private readonly ChromePdfRenderer _renderer;
public InvoiceService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.MarginTop = 10;
_renderer.RenderingOptions.MarginBottom = 10;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GenerateInvoice(Invoice invoice)
{
var html = BuildInvoiceHtml(invoice);
// Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
MaxHeight = 15,
HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
DrawDividerLine = true
};
var pdf = _renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
private string BuildInvoiceHtml(Invoice invoice)
{
var subtotal = invoice.Items.Sum(i => i.Total);
var taxAmount = subtotal * (invoice.Tax / 100);
var total = subtotal + taxAmount;
var itemsHtml = string.Join("", invoice.Items.Select(item =>
$@"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"));
return $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>";
}
}public class InvoiceService
{
private readonly ChromePdfRenderer _renderer;
public InvoiceService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.MarginTop = 10;
_renderer.RenderingOptions.MarginBottom = 10;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GenerateInvoice(Invoice invoice)
{
var html = BuildInvoiceHtml(invoice);
// Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
MaxHeight = 15,
HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
DrawDividerLine = true
};
var pdf = _renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
private string BuildInvoiceHtml(Invoice invoice)
{
var subtotal = invoice.Items.Sum(i => i.Total);
var taxAmount = subtotal * (invoice.Tax / 100);
var total = subtotal + taxAmount;
var itemsHtml = string.Join("", invoice.Items.Select(item =>
$@"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"));
return $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>";
}
}Por último, crea un nuevo Controlador para acceder y crear facturas usando la API:
[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
private readonly InvoiceService _invoiceService;
public InvoiceController(InvoiceService invoiceService)
{
_invoiceService = invoiceService;
}
[HttpPost("generate")]
public IActionResult GenerateInvoice([FromBody] Invoice invoice)
{
try
{
var pdfBytes = _invoiceService.GenerateInvoice(invoice);
var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
return File(pdfBytes, "application/pdf", fileName);
}
catch (Exception ex)
{
return StatusCode(500, $"Error generating invoice: {ex.Message}");
}
}
}[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
private readonly InvoiceService _invoiceService;
public InvoiceController(InvoiceService invoiceService)
{
_invoiceService = invoiceService;
}
[HttpPost("generate")]
public IActionResult GenerateInvoice([FromBody] Invoice invoice)
{
try
{
var pdfBytes = _invoiceService.GenerateInvoice(invoice);
var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
return File(pdfBytes, "application/pdf", fileName);
}
catch (Exception ex)
{
return StatusCode(500, $"Error generating invoice: {ex.Message}");
}
}
}Para obtener funciones de facturación avanzadas, considere agregar códigos de barras , códigos QR , números de página y encabezados/pies de página personalizados . También puede implementar la compatibilidad con PDF/A para el archivo a largo plazo o integrarlo con flujos de trabajo de firma electrónica .
¿Cómo se ve la salida de la factura?
¿Cuáles son las consideraciones a tener en cuenta en la implementación de contenedores?
Aunque este tutorial se enfoca en el desarrollo local, aquí hay una breve descripción de cómo contenerizar su API de PDF:
¿Cómo creo un Dockerfile básico?
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PdfApiService.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# IronPDF requires additional dependencies on Linux
RUN apt-get update && apt-get install -y \
libgdiplus \
libc6-dev \
libx11-dev \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["dotnet", "PdfApiService.dll"]Para guías de despliegue detalladas para su API de PDF de .NET, vea:
- Documentación de Docker de IronPDF - Guía completa de contenerización
- Despliegue de IronPDF en Azure - Funciones de Azure y App Service
- Despliegue de IronPDF en AWS - Despliegue en Lambda y EC2
- Configuración de IronPDF en Linux - Configuración específica de Linux
- Ejecución como contenedor remoto - Contenedorización de IronPDF Engine
- Motor nativo vs. remoto : opciones de arquitectura de implementación
¿Cuáles son las mejores prácticas de manejo de errores?
Para programas tolerantes a fallos, implemente un controlador de errores global para obtener respuestas de error consistentes:
// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path);
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
ArgumentNullException => 400,
UnauthorizedAccessException => 401,
_ => 500
};
var response = new
{
error = "An error occurred processing your request",
message = ex.Message,
statusCode = context.Response.StatusCode
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path);
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
ArgumentNullException => 400,
UnauthorizedAccessException => 401,
_ => 500
};
var response = new
{
error = "An error occurred processing your request",
message = ex.Message,
statusCode = context.Response.StatusCode
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}Para escenarios específicos de solución de problemas de IronPDF, consulte:
¿Está listo para crear su API de PDF .NET de producción?
Ahora ha creado una sólida API de PDF .NET utilizando ASP.NET Core e IronPDF que maneja varios escenarios de generación de documentos. Esta API REST proporciona una base sólida para operaciones centralizadas de PDF en sus aplicaciones.
Conclusiones clave:
- IronPDF facilita la generación de PDF en proyectos de API web con renderizado basado en Chrome .
- Edite fácilmente archivos PDF existentes con las herramientas de edición avanzadas de IronPDF.
- Los principios de diseño RESTful garantizan que la API PDF sea intuitiva y fácil de mantener.
- El tratamiento adecuado de los errores y las medidas de seguridad son esenciales para la producción.
- La optimización del rendimiento a través de operaciones asincrónicas y almacenamiento en caché mejora la escalabilidad.
- Soporte completo para aplicaciones de escritorio y web con soluciones de documentos escalables.
IronPDF permite a los desarrolladores crear archivos PDF, guardar archivos PDF y convertir HTML de manera eficiente, lo que lo convierte en la API de PDF esencial para las aplicaciones modernas de .NET Framework.
¿Cuáles son los próximos pasos?
¿Listo para implementar IronPDF en su API de PDF de producción para .NET? Aquí están sus próximas acciones:
- Inicie su prueba gratuita - Pruebe IronPDF con funcionalidad completa en su entorno de desarrollo.
- Explore las funciones avanzadas : consulte las firmas digitales , los formularios PDF , la conformidad con PDF/A , la gestión de metadatos y otras funciones avanzadas de PDF .
- Escale con confianza : revise las opciones de licencia para sus necesidades de API de producción, incluidas extensiones y actualizaciones .
¡Construya su API de PDF para .NET hoy y optimice la generación de documentos en todo su ecosistema de aplicaciones con IronPDF!
Preguntas Frecuentes
¿Para qué se utiliza IronPDF en las aplicaciones .NET?
IronPDF se utiliza para generar, manipular y convertir archivos PDF dentro de aplicaciones .NET, por lo que es ideal para crear servicios PDF centralizados.
¿Cómo puede integrarse IronPDF con ASP.NET Core?
IronPDF puede integrarse con ASP.NET Core instalando el paquete IronPDF NuGet, lo que permite crear un servicio centralizado de generación de PDF.
¿Cuáles son las principales características de IronPDF para la generación de PDF?
Entre las principales funciones de IronPDF se incluyen la conversión de HTML a PDF, la fusión y división de PDF, la adición de encabezados y pies de página y la extracción de texto e imágenes.
¿Puede IronPDF manejar diseños PDF complejos?
Sí, IronPDF puede manejar diseños PDF complejos gracias a su capacidad para convertir contenido HTML y CSS en documentos PDF renderizados con precisión.
¿Es posible personalizar la creación de PDF con IronPDF?
Sí, IronPDF permite la personalización en la creación de PDF, incluida la configuración del tamaño de página, los márgenes y la adición de marcas de agua o anotaciones.
¿IronPDF soporta características de seguridad para PDF?
IronPDF es compatible con funciones de seguridad de PDF como la protección por contraseña y el cifrado para proteger los documentos PDF generados.
¿Qué formatos puede convertir IronPDF en PDF?
IronPDF puede convertir varios formatos en PDF, incluidos HTML, URL y archivos ASPX, lo que lo hace versátil para diferentes casos de uso.
¿Cómo gestiona IronPDF la generación de PDF a gran escala?
IronPDF está optimizado para el rendimiento, lo que le permite gestionar eficazmente tareas de generación de PDF a gran escala dentro de aplicaciones .NET.
¿Puede usarse IronPDF en aplicaciones basadas en la nube?
Sí, IronPDF se puede utilizar en aplicaciones basadas en la nube y admite la implementación en plataformas como Azure y AWS para servicios de PDF escalables.
¿Qué versiones de .NET admite IronPDF?
IronPDF es compatible con varias versiones de .NET, incluidas .NET Core y .NET Framework, lo que garantiza la compatibilidad con una amplia gama de proyectos.






