使用IRONPDF 如何使用IronPDF创建.NET PDF API Curtis Chau 已更新:2025年9月18日 下载 IronPDF NuGet 下载 DLL 下载 Windows 安装程序 免费试用 法学硕士副本 法学硕士副本 将页面复制为 Markdown 格式,用于 LLMs 在 ChatGPT 中打开 向 ChatGPT 咨询此页面 在双子座打开 向 Gemini 询问此页面 在 Grok 中打开 向 Grok 询问此页面 打开困惑 向 Perplexity 询问有关此页面的信息 分享 在 Facebook 上分享 分享到 X(Twitter) 在 LinkedIn 上分享 复制链接 电子邮件文章 在使用现代应用程序时,像您这样的.NET开发人员可能会发现需要构建一个集中的PDF生成服务。无论您是生成发票、报告、证书或合同,拥有一个专门的.NET PDF API对于高效管理PDF文件都是有益的。 那么它如何改善您的PDF生成任务呢? 它通过在桌面和Web应用程序之间提供一致性、可维护性和可扩展性来实现这一点。 从未有过如此轻松地管理文档内容、PDF页面和PDF表单字段。 在本教程中,您将学习如何使用ASP.NET Core和IronPDF,一个强大的.NET PDF库,构建一个可用于生产的PDF API。 我们将创建可以从HTML生成PDF、合并文档、添加水印并处理Web API中各种实际PDF生成场景的RESTful端点。 为什么构建一个专门的PDF API? 在深入研究代码之前,让我们了解为什么创建一个专门的PDF API是有意义的: *集中式逻辑:*所有 PDF 生成逻辑都集中在一个地方,使维护和更新更加便捷。 微服务架构:**非常适合面向服务的架构,其中不同的应用程序需要 PDF 功能。 性能优化:更容易为大型PDF文件、多页面和动态数据优化和扩展专用服务。 *语言无关:任何客户端应用程序都可以使用该 API,而无需考虑编程语言。 输出一致性:确保整个组织的所有PDF文档都保持一致的文档布局、段落格式和PDF内容。 准备好开始构建了吗? 下载IronPDF的免费试用版,并按此教程一起编程实现.NET Framework项目中的PDF文件创建。 IronPDF: 完整的.NET PDF库 IronPDF被认为是.NET开发人员的首选PDF库,提供了一套全面的功能,使Web API项目中的PDF生成过程简单可靠。 它建立在Chrome渲染引擎上,确保像素级精准的HTML到PDF转换,通常只需几行代码即可完成。 这在保持所有样式、JavaScript执行和响应布局的同时完成。 使IronPDF成为.NET PDF API开发的理想选择的关键能力有: *基于 Chrome 的渲染:*利用 Google Chrome 的渲染引擎,将 HTML 内容精确转换为 PDF 文档,并完全支持嵌入式图像和其他 Web 资源。 功能丰富:**支持编辑带有数字签名、PDF 表单、注释、加密、压缩等功能的新建和现有文档 创建安全的PDF文档: 使用加密、数字签名和文档保护来管理敏感的PDF内容。 支持多种输入格式:可使用 HTML、URL、图像和Office 文档创建 PDF 文档 高级操作:合并PDF页面、拆分文档、应用水印、创建互动PDF表单,并以编程方式操作PDF文件。 *跨平台支持:*可在 Windows、 Linux 、macOS、 Docker和云平台上运行 性能优化:**异步操作、高效的内存管理和快速渲染 如何设置您的PDF文档API项目? 让我们从创建一个新的ASP.NET Core Web API项目并安装必要的包开始。 前提条件 .NET 6.0 SDK或更高版本 Visual Studio 2022或Visual Studio Code Postman或类似的API测试工具,以测试您的PDF REST API 创建项目 首先,让我们创建一个项目,我们将在其中构建我们的PDF生成工具。 dotnet new webapi -n PdfApiService cd PdfApiService 安装 IronPDF 下一步是通过NuGet将IronPDF添加到您的项目中: dotnet add package IronPdf 或者,在Visual Studio中使用NuGet包管理器控制台: Install-Package IronPdf 项目结构 C#开发的一个重要方面是保持一个干净且结构良好的项目文件夹。 例如: 如何创建您的第一个PDF端点? 让我们构建一个简单的端点,将HTML转换为PDF格式。 首先,创建服务接口和实现: 创建PDF服务 首先,我们将在我们的IPdfService.cs文件中添加以下内容: public interface IPdfService { byte[] GeneratePdfFromHtml(string htmlContent); byte[] GeneratePdfFromUrl(string url); } public interface IPdfService { byte[] GeneratePdfFromHtml(string htmlContent); byte[] GeneratePdfFromUrl(string url); } $vbLabelText $csharpLabel 在PdfService.cs文件中,我们将添加: 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; } } $vbLabelText $csharpLabel PdfService处理将HTML转换为PDF的核心过程。 利用IronPDF的ChromePdfRenderer,此类设置了合理的默认值,如页面边距和背景渲染,以生成一个精美的最终文档。 当控制器传递原始HTML时,服务使用IronPDF将其呈现为专业质量的PDF,并将结果返回为字节数据,准备好下载。 此外,它还可以通过将URL直接转换为PDF来处理整个网页。 创建控制器 现在是为我们的API创建控制器的时间了。 这将提供一个可以从HTML生成PDF文件的API端点。 然后,能够下载并将PDF文档保存到您的系统中,以便进一步使用或共享。 // 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}"); } } } $vbLabelText $csharpLabel 然后,在HtmlRequest.cs文件中,我们将添加: // 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"; } $vbLabelText $csharpLabel 在第一个文件中,我们设置了一个简单的API端点,将HTML转换为可下载的PDF。 当有人通过简单的POST请求将HTML内容发送到api/pdf/html-to-pdf路由时,PdfController将任务传递给专用的服务,将其转换为PDF。 一旦PDF创建完成,控制器将它作为一个准备好下载的文件返回给用户。请求本身是使用HtmlRequest模型结构化的,该模型携带原始HTML和用于最终文档的可选文件名。 简而言之,此设置使得客户端可以轻松发送HTML并立即获得一个精美的PDF作为返回。 注册服务 更新您的Program.cs以注册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(); $vbLabelText $csharpLabel 如何处理不同的响应类型? 您的API应该支持基于客户端需求以不同方式返回PDF: [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); } } $vbLabelText $csharpLabel 在这里,我们在控制器中添加了一个更灵活的PDF生成端点。 而不是总是强制下载文件,GeneratePdf方法让客户端选择他们希望结果如何返回。 此选项提供灵活性,允许PDF以多种格式显示:作为可下载文件,直接在浏览器中,或编码为Base64字符串以便在API中轻松使用。 请求由PdfRequest模型定义,该模型基于之前的HtmlRequest,并添加一个ResponseType选项。 总之,这使用户能够更好地控制如何接收他们的PDF,使API更加多样化和用户友好。 现在,当我们运行程序时,我们将在Swagger上看到此输出。 如何实现常见的PDF操作? 让我们扩展我们的服务以处理各种PDF生成场景: URL到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; } } $vbLabelText $csharpLabel 此端点允许客户端发送一个URL并获取该网页的可下载PDF。 当POST /api/pdf/url-to-pdf请求到达时,控制器使用_pdfService后台将给定的URL转换为PDF字节,然后以文件下载的形式返回。 如果在转换过程中出现问题,它会优雅地响应一个清晰的错误信息。 让我们尝试使用网址"https://www.apple.com/nz"并测试POST请求。下面是我们获得的输出。 输出 添加自定义水印 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; } $vbLabelText $csharpLabel 在这里,我们只是手动加载一个本地的文件以进行测试。 然而,您可以调整这个,以便您的PDF API生成PDF文档,然后轻松地应用自定义水印。 水印输出 如何使用模板添加动态数据 对于真实世界的应用程序,您通常需要从模板生成带有动态数据的PDFs: [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"; } $vbLabelText $csharpLabel 对于更高级的模板场景,请查看IronPDF的HTML到PDF文档。 您还可以探索CSHTML到PDF转换用于MVC应用程序和Razor到PDF用于Blazor应用程序。 如何优化性能? 在构建生产PDF API时,性能至关重要。 以下是关键的优化策略: 异步操作 当构建涉及使用I/O操作的项目时,明智的做法是使用异步编码。 如果您的PDF内容来自外部资源,这尤其有用,例如: 下载HTML页面(RenderUrlAsPdf) 通过HTTP获取图像、CSS或字体 读取/写入磁盘或云存储的文件 这些操作可以阻塞线程,但使用异步可以防止您的API线程空闲等待。 例: 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; }); } $vbLabelText $csharpLabel 渲染选项 配置IronPDF以获得最佳性能: _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 timeout $vbLabelText $csharpLabel 如何保护您的PDF API? 对于任何生产API,安全性都是至关重要的。 这里是一个简单的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>(); $vbLabelText $csharpLabel 对于更高级的身份验证场景,请考虑: JWT身份验证 - API身份验证的行业标准 OAuth 2.0 - 用于第三方集成 Azure AD集成 - 企业身份验证 API速率限制 - 防止滥用并确保公平使用 实际案例:发票生成API 让我们构建一个实际的发票生成端点,演示完整的实现。 此示例展示了如何使用生产.NET PDF API生成具有动态数据的专业发票。 立即开始使用 IronPDF。 免费开始 首先,我们将在我们的Models文件夹中创建一个新文件。 在这里,我将其称之为Invoice.cs。 然后,将以下代码添加到您的新文件中。 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; } $vbLabelText $csharpLabel 然后,我们将需要为我们的发票生成器创建一个新的服务文件。 在您的Services文件夹中,添加以下代码。 对于我的,我创建了一个名为InvoiceService.cs的新文件。 这段代码将处理我们的发票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>"; } } $vbLabelText $csharpLabel 最后,您将需要创建一个新的控制器,以便通过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}"); } } } $vbLabelText $csharpLabel 发票输出 容器部署注意事项 虽然本教程侧重于本地开发,但这里是关于将您的PDF API容器化的简要概述: 基础Dockerfile 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 . <h1>IronPDF requires additional dependencies on Linux</h1> RUN apt-get update && apt-get install -y \ libgdiplus \ libc6-dev \ libx11-dev \ && rm -rf /var/lib/apt/lists/* ENTRYPOINT ["dotnet", "PdfApiService.dll"] 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 . <h1>IronPDF requires additional dependencies on Linux</h1> RUN apt-get update && apt-get install -y \ libgdiplus \ libc6-dev \ libx11-dev \ && rm -rf /var/lib/apt/lists/* ENTRYPOINT ["dotnet", "PdfApiService.dll"] $vbLabelText $csharpLabel 有关您的.NET PDF API的详细部署指南,请参阅: IronPDF Docker文档 - 完整的容器化指南 IronPDF Azure部署 - Azure Functions和App Service IronPDF AWS部署 - Lambda和EC2部署 IronPDF Linux设置 - Linux特定配置 错误处理最佳实践 为了设计更具容错性的程序,最佳实践是实施全局错误处理程序,以获得一致的错误响应,例如下面所示: // Middleware/ErrorHandlingMiddleware.cs public class ErrorHandlingMiddleware { private readonly RequestDelegate _next; public ErrorHandlingMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { try { await _next(context); } catch (Exception ex) { await HandleExceptionAsync(context, ex); } } private static async Task HandleExceptionAsync(HttpContext context, Exception ex) { context.Response.ContentType = "application/json"; context.Response.StatusCode = 500; var response = new { error = "An error occurred processing your request", message = ex.Message }; await context.Response.WriteAsync(JsonSerializer.Serialize(response)); } } // Middleware/ErrorHandlingMiddleware.cs public class ErrorHandlingMiddleware { private readonly RequestDelegate _next; public ErrorHandlingMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { try { await _next(context); } catch (Exception ex) { await HandleExceptionAsync(context, ex); } } private static async Task HandleExceptionAsync(HttpContext context, Exception ex) { context.Response.ContentType = "application/json"; context.Response.StatusCode = 500; var response = new { error = "An error occurred processing your request", message = ex.Message }; await context.Response.WriteAsync(JsonSerializer.Serialize(response)); } } $vbLabelText $csharpLabel 对于特定的IronPDF故障排除场景,请参阅IronPDF故障排除指南。 结论 您现在已经构建了一个强大的.NET PDF API,使用ASP.NET Core和IronPDF可以处理多种文档生成场景。 这个REST API为您的应用程序提供集中化PDF操作的坚实基础。 关键要点: IronPDF使得Web API项目中的PDF生成变得简单,具有其基于Chrome的渲染 您可以轻松调整Web API以编辑现有PDF文档,利用IronPDF的高级编辑工具 RESTful设计原则确保您的PDF API直观且易于维护 适当的错误处理和安全措施对于生产至关重要 通过异步操作和缓存进行性能优化可提高可扩展性 您将拥有支持桌面和Web应用程序的可扩展文档解决方案 IronPDF允许开发人员高效地创建PDF文档、保存PDF文件和转换HTML,使其成为现代.NET Framework应用程序中的必备PDF文档API。 下一步 准备好在您的生产.NET PDF API中实施IronPDF了吗? 以下是您的下一步操作: 开始免费试用 - 在您的开发环境中测试IronPDF的全部功能 探索高级功能 - 查看数字签名、PDF表单和其他高级PDF功能 自信地扩展 - 查看许可选项以满足您的生产API需求 今天就构建您的.NET PDF API,并通过IronPDF在整个应用程序生态系统中简化文档生成! 常见问题解答 什么是.NET PDF API? 一个.NET PDF API是一个库,允许开发人员在.NET应用程序中创建、编辑和提取PDF内容。它简化了复杂的PDF任务并确保PDF文件的有效管理。 一个.NET PDF API如何能够使我的应用程序受益? 一个.NET PDF API可以通过提供一致性、可维护性和可扩展性来增强您的应用程序中PDF文件的管理,如生成发票、报告、证书或合同。 一个.NET PDF API 有哪些常见用例? 一个.NET PDF API 的常见用例包括在桌面和网络应用程序中生成发票、创建报告、制作证书和管理合同。 IronPDF如何简化PDF生成任务? IronPDF通过提供强大的库简化了PDF生成任务,使得文档内容、PDF页面和表单字段的管理变得简单,更容易维护和扩展应用程序。 IronPDF能够处理PDF表单字段吗? 是的,IronPDF可以高效管理PDF表单字段,允许开发者在PDF文件中创建、填写和提取表单数据。 IronPDF适用于桌面和网络应用程序吗? 当然,IronPDF专为跨桌面和网络应用程序无缝工作而设计,提供一致且可扩展的PDF管理解决方案。 是什么让IronPDF成为.NET开发人员可靠的选择? IronPDF是.NET开发人员可靠的选择,因为其使用简单、功能全面,并能够简化PDF任务,从而提高生产力和应用程序性能。 IronPDF支持PDF提取功能吗? 是的,IronPDF支持PDF提取功能,允许您有效地从PDF文件中提取文本、图像和其他数据。 IronPDF如何在管理PDF方面提高可扩展性? IronPDF通过提供一个集中化的PDF生成服务来提高可扩展性,它可以在不牺牲性能的情况下处理日益增长的需求,非常适合增长中的应用程序。 IronPDF为.NET应用程序提供了什么样的支持? IronPDF为.NET应用程序提供了广泛的支持,包括详细的文档、示例代码和响应迅速的支持团队,协助开发者集成PDF功能。 IronPDF 是否完全兼容 .NET 10? 是的——IronPDF 与 .NET 10 完全兼容。它支持 .NET 10 引入的所有性能、语言和运行时增强功能,并且可以像在 .NET 6、7、8 和 9 等以前的版本中一样,在 .NET 10 项目中开箱即用。 Curtis Chau 立即与工程团队聊天 技术作家 Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。 相关文章 已更新2026年1月22日 如何使用 IronPDF 在 .NET 中创建 PDF 文档:完整指南 发现为开发人员创建PDF文件的有效方法。提升您的编码技能并简化您的项目。立即阅读文章! 阅读更多 已更新2026年1月21日 如何在 VB.NET 中合并 PDF 文件:完整教程 使用IronPDF合并PDF VB NET。学习使用简单的VB.NET代码将多个PDF文件合并为一个文档。包括逐步示例。 阅读更多 已更新2026年1月21日 C# PDFWriter 教程:在 .NET 中创建 PDF 文档 使用这份逐步指南了解如何高效地使用C# PDFWriter创建PDF。阅读文章提升您的技能! 阅读更多 如何使用Azure和IronPDF将HTML转换为PDF如何使用 C# PDFWriter 创建 PD...
已更新2026年1月21日 如何在 VB.NET 中合并 PDF 文件:完整教程 使用IronPDF合并PDF VB NET。学习使用简单的VB.NET代码将多个PDF文件合并为一个文档。包括逐步示例。 阅读更多