使用IRONPDF 如何使用IronPDF创建.NET PDF API Curtis Chau 已更新:九月 18, 2025 Download IronPDF NuGet 下载 DLL 下载 Windows 安装程序 Start Free Trial Copy for LLMs Copy for LLMs Copy page as Markdown for LLMs Open in ChatGPT Ask ChatGPT about this page Open in Gemini Ask Gemini about this page Open in Grok Ask Grok about this page Open in Perplexity Ask Perplexity about this page Share Share on Facebook Share on X (Twitter) Share on LinkedIn Copy URL Email article 在使用现代应用程序时,像您这样的.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资产 Rich Feature Set: Supports the editing of new and existing documents with digital signatures, PDF forms, annotations, encryption, compression, and more 创建安全的PDF文档: 使用加密、数字签名和文档保护来管理敏感的PDF内容。 Multiple Input Formats: Use HTML, URLs, images, and Office documents to create PDF documents 高级操作:合并PDF页面、拆分文档、应用水印、创建互动PDF表单,并以编程方式操作PDF文件。 Cross-Platform Support: Works on Windows, Linux, macOS, Docker, and cloud platforms 性能优化:异步操作、高效的内存管理和快速渲染 如何设置您的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); } IRON VB CONVERTER ERROR developers@ironsoftware.com $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; } } IRON VB CONVERTER ERROR developers@ironsoftware.com $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}"); } } } IRON VB CONVERTER ERROR developers@ironsoftware.com $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"; } IRON VB CONVERTER ERROR developers@ironsoftware.com $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(); IRON VB CONVERTER ERROR developers@ironsoftware.com $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); } } IRON VB CONVERTER ERROR developers@ironsoftware.com $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; } } IRON VB CONVERTER ERROR developers@ironsoftware.com $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; } IRON VB CONVERTER ERROR developers@ironsoftware.com $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"; } IRON VB CONVERTER ERROR developers@ironsoftware.com $vbLabelText $csharpLabel 对于更高级的模板场景,请查看IronPDF的HTML到PDF文档。 You can also explore CSHTML to PDF conversion for MVC applications and Razor to PDF for Blazor applications. 如何优化性能? 在构建生产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; }); } IRON VB CONVERTER ERROR developers@ironsoftware.com $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 IRON VB CONVERTER ERROR developers@ironsoftware.com $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>(); IRON VB CONVERTER ERROR developers@ironsoftware.com $vbLabelText $csharpLabel 对于更高级的身份验证场景,请考虑: JWT身份验证 - API身份验证的行业标准 OAuth 2.0 - 用于第三方集成 Azure AD集成 - 企业身份验证 API速率限制 - 防止滥用并确保公平使用 Real-World 例: Invoice Generation 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; } IRON VB CONVERTER ERROR developers@ironsoftware.com $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>"; } } IRON VB CONVERTER ERROR developers@ironsoftware.com $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}"); } } } IRON VB CONVERTER ERROR developers@ironsoftware.com $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 . # 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"] 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"] IRON VB CONVERTER ERROR developers@ironsoftware.com $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)); } } IRON VB CONVERTER ERROR developers@ironsoftware.com $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的全部功能 Explore advanced features - Check out digital signatures, PDF forms, and other advanced PDF features 自信地扩展 - 查看许可选项以满足您的生产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 机器人,将他对技术的热爱与创造力相结合。 相关文章 已发布十一月 13, 2025 如何在 C# 中合并两个 PDF 字节数组 使用 IronPDF 在 C# 中合并两个 PDF 字节数组。学习通过简单的代码示例从字节数组、内存流和数据库合并多个 PDF 文件。 阅读更多 已发布十一月 13, 2025 如何创建 ASP.NET MVC PDF 查看器 为 ASP.NET MVC 应用程序构建一个强大的 PDF 查看器。显示 PDF 文档,将视图转换为 PDF,并使用 IronPDF 添加交互功能。 阅读更多 已发布十一月 13, 2025 如何构建 .NET HTML 到 PDF 转换器 学习如何使用 IronPDF 在 .NET 中将 HTML 转换为 PDF。 阅读更多 如何使用Azure和IronPDF将HTML转换为PDF如何使用C# PDFWriter创建PDF
已发布十一月 13, 2025 如何在 C# 中合并两个 PDF 字节数组 使用 IronPDF 在 C# 中合并两个 PDF 字节数组。学习通过简单的代码示例从字节数组、内存流和数据库合并多个 PDF 文件。 阅读更多
已发布十一月 13, 2025 如何创建 ASP.NET MVC PDF 查看器 为 ASP.NET MVC 应用程序构建一个强大的 PDF 查看器。显示 PDF 文档,将视图转换为 PDF,并使用 IronPDF 添加交互功能。 阅读更多