IronPDF 操作指南 TLS 网站和系统登录 在 C# 登录验证背后将 HTML 转换为 PDF; Curtis Chau 已更新:2026年1月10日 下载 IronPDF NuGet 下载 DLL 下载 Windows 安装程序 免费试用 LLM副本 LLM副本 将页面复制为 Markdown 格式,用于 LLMs 在 ChatGPT 中打开 向 ChatGPT 咨询此页面 在双子座打开 向 Gemini 询问此页面 在 Grok 中打开 向 Grok 询问此页面 打开困惑 向 Perplexity 询问有关此页面的信息 分享 在 Facebook 上分享 分享到 X(Twitter) 在 LinkedIn 上分享 复制链接 电子邮件文章 This article was translated from English: Does it need improvement? Translated View the article in English 要在 C# 中通过登录身份验证将 HTML 转换为 PDF,请使用 IronPDF 的 ChromeHttpLoginCredentials 进行网络身份验证,或者在转换之前使用 HttpClient 下载 HTML。 这种方法可以有效处理网络验证和 HTML 表单登录。 快速入门:使用IronPDF在登录后将 HTML 转换为 PDF 使用 IronPDF 的 API 将 HTML 页面转换为登录表单后面的 PDF。 本指南演示了 ChromeHttpLoginCredentials 的身份验证和受保护内容检索。 使用简单明了的代码示例处理网络身份验证和 HTML 表单登录。 使用 NuGet 包管理器安装 https://www.nuget.org/packages/IronPdf PM > Install-Package IronPdf 复制并运行这段代码。 new ChromePdfRenderer { LoginCredentials = new ChromeHttpLoginCredentials("username","password") } .RenderUrlAsPdf("https://example.com/protected") .SaveAs("secure.pdf"); 部署到您的生产环境中进行测试 通过免费试用立即在您的项目中开始使用IronPDF Free 30 Day Trial 最小工作流程(5 个步骤) 下载 C# IronPDF 库。 下载HTML以避免登录 通过 **`LoginCredentials`** 属性使用网络身份验证登录 使用HTML表单进行身份验证 MVC登录身份验证的解决方法 处理登录身份验证的最佳实践是什么? IronPDF 通过 ChromeHttpLoginCredentials API 支持 TLS 网络身份验证(用户名和密码)。 有关各种登录场景的全面指导,请参阅 TLS 网站和系统登录教程。 推荐的方法是使用 System.Net.WebClient 或 HttpClient 下载 HTML 和资源。 该方法支持标题、登录和其他要求。 下载到内存或磁盘后,IronPDF 会将 HTML 转换为 PDF。 使用 HtmlAgilityPack 提取样式表和图像等资源,然后使用 System.Net.WebClient 下载。 // Download HTML content from a URL with authentication string html; using (WebClient client = new WebClient()) { // Add authentication headers if needed client.Headers.Add("Authorization", "Bearer " + accessToken); // Download the HTML string html = client.DownloadString("http://www.example.com/protected-content"); } // Load the HTML into an HtmlDocument for parsing HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(html); // Extract all image sources for downloading foreach(HtmlNode img in doc.DocumentNode.SelectNodes("//img")) { string imgSrc = img.GetAttributeValue("src", null); Console.WriteLine($"Found image: {imgSrc}"); // Download each image asset if (!string.IsNullOrEmpty(imgSrc)) { string fileName = Path.GetFileName(imgSrc); client.DownloadFile(imgSrc, fileName); } } // Convert the downloaded HTML to PDF var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(html); pdf.SaveAs("authenticated-content.pdf"); // Download HTML content from a URL with authentication string html; using (WebClient client = new WebClient()) { // Add authentication headers if needed client.Headers.Add("Authorization", "Bearer " + accessToken); // Download the HTML string html = client.DownloadString("http://www.example.com/protected-content"); } // Load the HTML into an HtmlDocument for parsing HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(html); // Extract all image sources for downloading foreach(HtmlNode img in doc.DocumentNode.SelectNodes("//img")) { string imgSrc = img.GetAttributeValue("src", null); Console.WriteLine($"Found image: {imgSrc}"); // Download each image asset if (!string.IsNullOrEmpty(imgSrc)) { string fileName = Path.GetFileName(imgSrc); client.DownloadFile(imgSrc, fileName); } } // Convert the downloaded HTML to PDF var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(html); pdf.SaveAs("authenticated-content.pdf"); $vbLabelText $csharpLabel 请注意使用重载的 System.Uri 构造函数将相对 URL 重新定位为绝对 URL。 要重新定义 HTML 文档中的所有相对路径,请使用 HtmlAgilityPack 将 <base> 标签添加到标头。 示例。 有关处理 URL 和资源的更多信息,请参阅"基本 URL 和资源编码"指南。 为什么要先下载 HTML 内容? 在转换之前下载 HTML 内容有几个优势: 1.完全控制:在转换前修改 HTML、修复断开的链接或注入验证令牌 2.资产管理:下载和缓存图片、CSS 和 JavaScript 文件等外部资源 3.身份验证灵活性:使用任何 .NET 身份验证机制,包括 OAuth、JWT 标记或自定义标头 4.性能:缓存经常访问的内容,减少服务器负载 5.调试:检查正在转换的确切 HTML 以排除故障 有关涉及 cookie 和会话的复杂身份验证场景,请参阅 Cookies 指南,其中解释了 PDF 转换过程中的身份验证状态管理。 如何处理图片和样式表等资产? 在转换已通过身份验证的页面时,外部资产通常需要同样的身份验证。 以下是使用 HttpClient 的全面方法: public async Task<string> DownloadAuthenticatedHtmlWithAssets(string url, string authToken) { using (var client = new HttpClient()) { // Set authentication header client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken); // Download the main HTML string html = await client.GetStringAsync(url); // Parse HTML to find assets var doc = new HtmlDocument(); doc.LoadHtml(html); // Create a base URI for resolving relative paths var baseUri = new Uri(url); // Download CSS files var cssLinks = doc.DocumentNode.SelectNodes("//link[@rel='stylesheet']"); if (cssLinks != null) { foreach (var link in cssLinks) { string href = link.GetAttributeValue("href", ""); if (!string.IsNullOrEmpty(href)) { var cssUri = new Uri(baseUri, href); string cssContent = await client.GetStringAsync(cssUri); // Embed CSS directly in the HTML var styleNode = doc.CreateElement("style"); styleNode.InnerHtml = cssContent; doc.DocumentNode.SelectSingleNode("//head").AppendChild(styleNode); // Remove the external link link.Remove(); } } } // Return the modified HTML with embedded assets return doc.DocumentNode.OuterHtml; } } public async Task<string> DownloadAuthenticatedHtmlWithAssets(string url, string authToken) { using (var client = new HttpClient()) { // Set authentication header client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken); // Download the main HTML string html = await client.GetStringAsync(url); // Parse HTML to find assets var doc = new HtmlDocument(); doc.LoadHtml(html); // Create a base URI for resolving relative paths var baseUri = new Uri(url); // Download CSS files var cssLinks = doc.DocumentNode.SelectNodes("//link[@rel='stylesheet']"); if (cssLinks != null) { foreach (var link in cssLinks) { string href = link.GetAttributeValue("href", ""); if (!string.IsNullOrEmpty(href)) { var cssUri = new Uri(baseUri, href); string cssContent = await client.GetStringAsync(cssUri); // Embed CSS directly in the HTML var styleNode = doc.CreateElement("style"); styleNode.InnerHtml = cssContent; doc.DocumentNode.SelectSingleNode("//head").AppendChild(styleNode); // Remove the external link link.Remove(); } } } // Return the modified HTML with embedded assets return doc.DocumentNode.OuterHtml; } } $vbLabelText $csharpLabel 哪些工具有助于 HTML 解析? HtmlAgilityPack 是.NET中最流行的 HTML 解析库,但也有其他替代方案: 1.HtmlAgilityPack:最适用于一般 HTML 解析和操作 2.AngleSharp:符合标准的现代 HTML 解析器,支持 CSS 选择器 3.CsQuery:为熟悉 jQuery 的 C# 开发人员提供类似 jQuery 的语法 4.常规表达式:适用于简单的提取任务(不建议用于复杂的 HTML) 如何使用网络身份验证登录? 大多数ASP.NET应用程序支持网络身份验证,这比HTML表单提交更可靠。 IronPDF通过 ChromeHttpLoginCredentials 类提供对基本身份验证、摘要身份验证和 NTLM 身份验证的内置支持。 有关其他标头定制,请参阅 HTTP 请求标头指南。 :path=/static-assets/pdf/content-code-examples/how-to/logins-username-password.cs using IronPdf; using System; ChromePdfRenderer renderer = new ChromePdfRenderer { // setting login credentials to bypass basic authentication LoginCredentials = new ChromeHttpLoginCredentials() { NetworkUsername = "testUser", NetworkPassword = "testPassword" } }; var uri = new Uri("http://localhost:51169/Invoice"); // Render web URL to PDF PdfDocument pdf = renderer.RenderUrlAsPdf(uri); // Export PDF pdf.SaveAs("UrlToPdfExample.Pdf"); $vbLabelText $csharpLabel 为什么网络验证比表单发布更可靠? 与 HTML 表单发布相比,网络验证具有多项优势: 1.标准化协议:使用符合 RFC 标准的 HTTP 验证标头 2.浏览器集成:Chrome 浏览器呈现引擎可无缝处理身份验证 3.会话管理:自动处理身份验证挑战和会话持久性 4.安全性:通过标头而非表单数据安全传输凭证 5.兼容性:可与大多数企业身份验证系统配合使用(Active Directory, LDAP) 网络身份验证需要哪些凭证? 不同的验证类型需要不同的证书: // Basic Authentication (most common) var basicAuth = new ChromeHttpLoginCredentials { NetworkUsername = "user@domain.com", NetworkPassword = "password123", AuthenticationType = ChromeHttpLoginCredentials.AuthType.Basic }; // NTLM/Windows Authentication var ntlmAuth = new ChromeHttpLoginCredentials { NetworkUsername = "DOMAIN\\username", // Include domain NetworkPassword = "password123", AuthenticationType = ChromeHttpLoginCredentials.AuthType.Ntlm }; // Custom authentication headers var renderer = new ChromePdfRenderer(); renderer.RenderingOptions.CustomHttpHeaders.Add("X-API-Key", "your-api-key"); renderer.RenderingOptions.CustomHttpHeaders.Add("Authorization", "Bearer " + jwtToken); // Basic Authentication (most common) var basicAuth = new ChromeHttpLoginCredentials { NetworkUsername = "user@domain.com", NetworkPassword = "password123", AuthenticationType = ChromeHttpLoginCredentials.AuthType.Basic }; // NTLM/Windows Authentication var ntlmAuth = new ChromeHttpLoginCredentials { NetworkUsername = "DOMAIN\\username", // Include domain NetworkPassword = "password123", AuthenticationType = ChromeHttpLoginCredentials.AuthType.Ntlm }; // Custom authentication headers var renderer = new ChromePdfRenderer(); renderer.RenderingOptions.CustomHttpHeaders.Add("X-API-Key", "your-api-key"); renderer.RenderingOptions.CustomHttpHeaders.Add("Authorization", "Bearer " + jwtToken); $vbLabelText $csharpLabel 如何排除身份验证失败? 常见的身份验证问题和解决方案: 1.401 未授权:检查凭证和验证类型 2.403 禁止:用户已通过身份验证,但缺乏权限 3.超时错误:对于速度较慢的身份验证系统,请增加 RenderDelay 4.证书错误:正确配置 TLS/SSL 设置 启用调试功能以诊断问题: // Enable detailed logging IronPdf.Logging.Logger.EnableDebugging = true; IronPdf.Logging.Logger.LogFilePath = "IronPdf.log"; IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All; // Test authentication try { var pdf = renderer.RenderUrlAsPdf("https://secure.example.com"); pdf.SaveAs("authenticated.pdf"); } catch (Exception ex) { Console.WriteLine($"Authentication failed: {ex.Message}"); // Check IronPdf.log for detailed error information } // Enable detailed logging IronPdf.Logging.Logger.EnableDebugging = true; IronPdf.Logging.Logger.LogFilePath = "IronPdf.log"; IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All; // Test authentication try { var pdf = renderer.RenderUrlAsPdf("https://secure.example.com"); pdf.SaveAs("authenticated.pdf"); } catch (Exception ex) { Console.WriteLine($"Authentication failed: {ex.Message}"); // Check IronPdf.log for detailed error information } $vbLabelText $csharpLabel 如何使用 HTML 表单登录? 要通过向 HTML 表单发送数据来登录,请使用 ChromeHttpLoginCredentials 类。 请参阅 IronPdf 的 ChromeHttpLoginCredentials API.. 请考虑以下几点: 将登录数据发布到 HTML 表单 ACTION 属性中指定的 URL。 将此设置为 HttpLoginCredentials 的 LoginFormUrl 属性。 这可能与您希望呈现为 PDF 的 URL 有所不同。 发送代表 HTML 表单中每个输入和文本区域的数据。 name 属性定义了每个变量的名称(而不是 id)。 有些网站会主动防止机器登录。 以下是基于表单的身份验证的完整示例: // Configure form-based login var formLogin = new ChromeHttpLoginCredentials { LoginFormUrl = "https://example.com/login", LoginFormData = new Dictionary<string, string> { {"username", "user@example.com"}, {"password", "securePassword123"}, {"rememberMe", "true"}, {"csrf_token", "abc123"} // Include any hidden fields } }; var renderer = new ChromePdfRenderer { LoginCredentials = formLogin, RenderingOptions = new ChromePdfRenderOptions { RenderDelay = 3000, // Allow time for login redirect EnableJavaScript = true } }; // The actual page you want to convert (after login) var pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard"); pdf.SaveAs("dashboard.pdf"); // Configure form-based login var formLogin = new ChromeHttpLoginCredentials { LoginFormUrl = "https://example.com/login", LoginFormData = new Dictionary<string, string> { {"username", "user@example.com"}, {"password", "securePassword123"}, {"rememberMe", "true"}, {"csrf_token", "abc123"} // Include any hidden fields } }; var renderer = new ChromePdfRenderer { LoginCredentials = formLogin, RenderingOptions = new ChromePdfRenderOptions { RenderDelay = 3000, // Allow time for login redirect EnableJavaScript = true } }; // The actual page you want to convert (after login) var pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard"); pdf.SaveAs("dashboard.pdf"); $vbLabelText $csharpLabel 我需要捕获哪些表单数据? 要通过 HTML 表单成功进行身份验证,请捕捉所有表单输入: // Use this helper method to extract form fields public Dictionary<string, string> ExtractFormFields(string loginPageHtml) { var formData = new Dictionary<string, string>(); var doc = new HtmlDocument(); doc.LoadHtml(loginPageHtml); // Find all input fields var inputs = doc.DocumentNode.SelectNodes("//input"); if (inputs != null) { foreach (var input in inputs) { string name = input.GetAttributeValue("name", ""); string value = input.GetAttributeValue("value", ""); string type = input.GetAttributeValue("type", "text"); if (!string.IsNullOrEmpty(name)) { // Handle different input types switch (type.ToLower()) { case "checkbox": if (input.Attributes["checked"] != null) formData[name] = "on"; break; case "radio": if (input.Attributes["checked"] != null) formData[name] = value; break; default: formData[name] = value; break; } } } } // Don't forget select elements var selects = doc.DocumentNode.SelectNodes("//select"); if (selects != null) { foreach (var select in selects) { string name = select.GetAttributeValue("name", ""); var selected = select.SelectSingleNode(".//option[@selected]"); if (selected != null && !string.IsNullOrEmpty(name)) { formData[name] = selected.GetAttributeValue("value", ""); } } } return formData; } // Use this helper method to extract form fields public Dictionary<string, string> ExtractFormFields(string loginPageHtml) { var formData = new Dictionary<string, string>(); var doc = new HtmlDocument(); doc.LoadHtml(loginPageHtml); // Find all input fields var inputs = doc.DocumentNode.SelectNodes("//input"); if (inputs != null) { foreach (var input in inputs) { string name = input.GetAttributeValue("name", ""); string value = input.GetAttributeValue("value", ""); string type = input.GetAttributeValue("type", "text"); if (!string.IsNullOrEmpty(name)) { // Handle different input types switch (type.ToLower()) { case "checkbox": if (input.Attributes["checked"] != null) formData[name] = "on"; break; case "radio": if (input.Attributes["checked"] != null) formData[name] = value; break; default: formData[name] = value; break; } } } } // Don't forget select elements var selects = doc.DocumentNode.SelectNodes("//select"); if (selects != null) { foreach (var select in selects) { string name = select.GetAttributeValue("name", ""); var selected = select.SelectSingleNode(".//option[@selected]"); if (selected != null && !string.IsNullOrEmpty(name)) { formData[name] = selected.GetAttributeValue("value", ""); } } } return formData; } $vbLabelText $csharpLabel 如何找到正确的表单操作 URL? 表单操作 URL 对于成功验证至关重要: public string ExtractFormAction(string loginPageUrl, string loginPageHtml) { var doc = new HtmlDocument(); doc.LoadHtml(loginPageHtml); // Find the login form var form = doc.DocumentNode.SelectSingleNode("//form[contains(@action, 'login') or contains(@id, 'login') or contains(@class, 'login')]"); if (form == null) { // Try finding any form with password field form = doc.DocumentNode.SelectSingleNode("//form[.//input[@type='password']]"); } if (form != null) { string action = form.GetAttributeValue("action", ""); // Resolve relative URLs if (!string.IsNullOrEmpty(action)) { var baseUri = new Uri(loginPageUrl); var actionUri = new Uri(baseUri, action); return actionUri.ToString(); } } // Default to the login page URL if no action found return loginPageUrl; } public string ExtractFormAction(string loginPageUrl, string loginPageHtml) { var doc = new HtmlDocument(); doc.LoadHtml(loginPageHtml); // Find the login form var form = doc.DocumentNode.SelectSingleNode("//form[contains(@action, 'login') or contains(@id, 'login') or contains(@class, 'login')]"); if (form == null) { // Try finding any form with password field form = doc.DocumentNode.SelectSingleNode("//form[.//input[@type='password']]"); } if (form != null) { string action = form.GetAttributeValue("action", ""); // Resolve relative URLs if (!string.IsNullOrEmpty(action)) { var baseUri = new Uri(loginPageUrl); var actionUri = new Uri(baseUri, action); return actionUri.ToString(); } } // Default to the login page URL if no action found return loginPageUrl; } $vbLabelText $csharpLabel 基于表单的身份验证有哪些常见问题? 1.CSRF 标记:许多表单都包含过期的防伪造令牌 2.JavaScript验证:某些表单需要执行 JavaScript 3.多步骤身份验证:需要多个页面的表单 4.验证码保护:人工验证挑战 5.会话超时:快速过期的登录会话 如何处理反僵尸保护? 现代网站都有防止自动登录的功能: // Strategies for handling anti-bot measures var renderer = new ChromePdfRenderer { RenderingOptions = new ChromePdfRenderOptions { // Mimic real browser behavior ViewPortWidth = 1920, ViewPortHeight = 1080, EnableJavaScript = true, RenderDelay = 5000, // Wait for JavaScript // Set a real user agent CustomHttpHeaders = new Dictionary<string, string> { {"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"} } } }; // For sites with rate limiting, add delays between requests System.Threading.Thread.Sleep(2000); // Strategies for handling anti-bot measures var renderer = new ChromePdfRenderer { RenderingOptions = new ChromePdfRenderOptions { // Mimic real browser behavior ViewPortWidth = 1920, ViewPortHeight = 1080, EnableJavaScript = true, RenderDelay = 5000, // Wait for JavaScript // Set a real user agent CustomHttpHeaders = new Dictionary<string, string> { {"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"} } } }; // For sites with rate limiting, add delays between requests System.Threading.Thread.Sleep(2000); $vbLabelText $csharpLabel 如需了解全面的 HTML 至 PDF 转换指导,包括复杂的验证场景,请访问 HTML 至 PDF 教程。 如何处理 MVC 身份验证? 以下变通方法可通过编程将 .NET MVC 视图渲染为字符串,从而在忠实渲染视图的同时避免 MVC 登录。 这种方法在将 CSHTML 转换为 MVC Core 中的 PDF 或 MVC Framework 时效果很好。 // Converts an MVC partial view to a string public static string RenderPartialViewToString(this Controller controller, string viewPath, object model = null) { try { // Set the model var context = controller.ControllerContext; controller.ViewData.Model = model; using (var sw = new StringWriter()) { // Find the partial view var viewResult = ViewEngines.Engines.FindPartialView(context, viewPath); if (viewResult.View == null) { throw new Exception($"Partial view {viewPath} could not be found."); } // Create a view context var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw); // Render the view viewResult.View.Render(viewContext, sw); viewResult.ViewEngine.ReleaseView(context, viewResult.View); return sw.GetStringBuilder().ToString(); } } catch (Exception ex) { // Return error message if there is an exception return ex.Message; } } // Usage in an MVC Controller public ActionResult GeneratePdf() { // Render authenticated view to string var model = new InvoiceViewModel { /* populate model */ }; string html = this.RenderPartialViewToString("~/Views/Invoice/Details.cshtml", model); // Convert to PDF var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(html); // Return PDF file return File(pdf.BinaryData, "application/pdf", "invoice.pdf"); } // Converts an MVC partial view to a string public static string RenderPartialViewToString(this Controller controller, string viewPath, object model = null) { try { // Set the model var context = controller.ControllerContext; controller.ViewData.Model = model; using (var sw = new StringWriter()) { // Find the partial view var viewResult = ViewEngines.Engines.FindPartialView(context, viewPath); if (viewResult.View == null) { throw new Exception($"Partial view {viewPath} could not be found."); } // Create a view context var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw); // Render the view viewResult.View.Render(viewContext, sw); viewResult.ViewEngine.ReleaseView(context, viewResult.View); return sw.GetStringBuilder().ToString(); } } catch (Exception ex) { // Return error message if there is an exception return ex.Message; } } // Usage in an MVC Controller public ActionResult GeneratePdf() { // Render authenticated view to string var model = new InvoiceViewModel { /* populate model */ }; string html = this.RenderPartialViewToString("~/Views/Invoice/Details.cshtml", model); // Convert to PDF var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(html); // Return PDF file return File(pdf.BinaryData, "application/pdf", "invoice.pdf"); } $vbLabelText $csharpLabel 为什么将视图渲染为字符串而不是直接转换? 将 MVC 视图渲染为字符串具有几个关键优势: 1.验证上下文:视图在已验证用户的上下文中呈现 2.完整的 MVC 管道:所有 MVC 功能均可正常工作,包括 TempData 和 Html 辅助函数 3.布局支持:正确呈现主页面和布局 4.模型绑定:复杂视图模型的无缝运行 5.动作过滤器:安全和日志过滤器正常执行 该 MVC 解决方案有哪些优势? MVC 字符串渲染方法提供 安全性:无需暴露内部 URL 或绕过身份验证 性能:避免额外的 HTTP 请求 一致性:与用户在浏览器中看到的输出完全一致 灵活性:在 PDF 转换之前修改 HTML 测试:轻松生成单元测试 HTML 如何将模型传递给渲染视图? 下面是一个具有复杂模型的综合示例: public class InvoiceController : Controller { private readonly IInvoiceService _invoiceService; public async Task<ActionResult> DownloadInvoicePdf(int invoiceId) { // Load data within authenticated context var invoice = await _invoiceService.GetInvoiceAsync(invoiceId); if (invoice == null || invoice.UserId != User.Identity.GetUserId()) { return HttpNotFound(); } // Create view model var viewModel = new InvoiceDetailsViewModel { Invoice = invoice, Company = await _invoiceService.GetCompanyDetailsAsync(), LineItems = await _invoiceService.GetLineItemsAsync(invoiceId), TaxDetails = await _invoiceService.GetTaxDetailsAsync(invoiceId) }; // Render to HTML string string html = this.RenderPartialViewToString("~/Views/Invoice/DetailsPdf.cshtml", viewModel); // Add custom styling for PDF html = $@" <html> <head> <style> body {{ font-family: Arial, sans-serif; }} .invoice-header {{ background-color: #f0f0f0; padding: 20px; }} .line-items {{ width: 100%; border-collapse: collapse; }} .line-items th, .line-items td {{ border: 1px solid #ddd; padding: 8px; }} </style> </head> <body> {html} </body> </html>"; // Convert to PDF with options var renderer = new ChromePdfRenderer { RenderingOptions = new ChromePdfRenderOptions { MarginTop = 20, MarginBottom = 20, MarginLeft = 10, MarginRight = 10, PrintHtmlBackgrounds = true } }; var pdf = renderer.RenderHtmlAsPdf(html); // Add metadata pdf.MetaData.Author = "Invoice System"; pdf.MetaData.Title = $"Invoice #{invoice.Number}"; pdf.MetaData.CreationDate = DateTime.Now; return File(pdf.BinaryData, "application/pdf", $"Invoice-{invoice.Number}.pdf"); } } public class InvoiceController : Controller { private readonly IInvoiceService _invoiceService; public async Task<ActionResult> DownloadInvoicePdf(int invoiceId) { // Load data within authenticated context var invoice = await _invoiceService.GetInvoiceAsync(invoiceId); if (invoice == null || invoice.UserId != User.Identity.GetUserId()) { return HttpNotFound(); } // Create view model var viewModel = new InvoiceDetailsViewModel { Invoice = invoice, Company = await _invoiceService.GetCompanyDetailsAsync(), LineItems = await _invoiceService.GetLineItemsAsync(invoiceId), TaxDetails = await _invoiceService.GetTaxDetailsAsync(invoiceId) }; // Render to HTML string string html = this.RenderPartialViewToString("~/Views/Invoice/DetailsPdf.cshtml", viewModel); // Add custom styling for PDF html = $@" <html> <head> <style> body {{ font-family: Arial, sans-serif; }} .invoice-header {{ background-color: #f0f0f0; padding: 20px; }} .line-items {{ width: 100%; border-collapse: collapse; }} .line-items th, .line-items td {{ border: 1px solid #ddd; padding: 8px; }} </style> </head> <body> {html} </body> </html>"; // Convert to PDF with options var renderer = new ChromePdfRenderer { RenderingOptions = new ChromePdfRenderOptions { MarginTop = 20, MarginBottom = 20, MarginLeft = 10, MarginRight = 10, PrintHtmlBackgrounds = true } }; var pdf = renderer.RenderHtmlAsPdf(html); // Add metadata pdf.MetaData.Author = "Invoice System"; pdf.MetaData.Title = $"Invoice #{invoice.Number}"; pdf.MetaData.CreationDate = DateTime.Now; return File(pdf.BinaryData, "application/pdf", $"Invoice-{invoice.Number}.pdf"); } } $vbLabelText $csharpLabel 在实施任何身份验证解决方案之前,请确保您已正确安装 IronPdf 并配置了许可证密钥。 准备好看看您还能做些什么吗? 请访问我们的教程页面:Convert PDFs. 常见问题解答 当内容位于登录表单之后时,如何将 HTML 转换为 PDF? IronPDF 提供了多种登录验证后将 HTML 转换为 PDF 的方法。您可以使用 ChromeHttpLoginCredentials API 进行 TLS 网络身份验证,也可以使用 System.Net.WebClient 或 HttpClient 下载 HTML 内容并加上适当的身份验证标头,然后再用 IronPDF 将其转换为 PDF。 什么是 ChromeHttpLoginCredentials,如何使用? ChromeHttpLoginCredentials 是 IronPDF 用于处理网络身份验证的 API。您可以通过在 ChromePdfRenderer 的 LoginCredentials 属性中设置用户名和密码来使用它,从而允许 IronPDF 在将受密码保护的 URL 呈现为 PDF 时自动进行身份验证。 我能否在 PDF 转换中处理基于 HTML 表单的登录? 是的,IronPDF 支持基于 HTML 表单的登录。推荐的方法是使用 System.Net.WebClient 或 HttpClient 来处理登录过程,下载经过验证的 HTML 内容,然后使用 IronPDF 的 RenderHtmlAsPdf 方法将下载的 HTML 转换为 PDF。 如何从认证页面下载图片和样式表等 HTML 资产? 您可以使用 HtmlAgilityPack 来解析下载的 HTML 并提取图片和样式表等资产 URL。然后使用 System.Net.WebClient 以相同的验证头下载每个资产,最后再用 IronPDF 将完整的 HTML 包转换为 PDF。 处理身份验证令牌或标头的最佳做法是什么? 在使用带有身份验证令牌的 IronPDF 时,请使用 HttpClient 或 WebClient 下载带有身份验证标头(如 Bearer 令牌)的 HTML。将经过验证的 HTML 内容存储到内存或磁盘中后,使用 IronPDF 的 ChromePdfRenderer 将其转换为 PDF。 MVC 登录身份验证是否有变通方法? 是的,IronPDF 为 MVC 登录验证方案提供了变通方法。建议的方法是首先使用标准 .NET HTTP 客户端进行身份验证并下载 HTML 内容,然后将经过身份验证的 HTML 直接传递给 IronPDF 的渲染引擎,而不是由 IronPDF 来处理身份验证。 Curtis Chau 立即与工程团队聊天 技术作家 Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。 准备开始了吗? Nuget 下载 17,803,474 | 版本: 2026.3 刚刚发布 免费试用 免费 NuGet 下载 总下载量:17,803,474 查看许可证 还在滚动吗? 想快速获得证据? PM > Install-Package IronPdf 运行示例看着你的HTML代码变成PDF文件。 免费 NuGet 下载 总下载量:17,803,474 查看许可证