迁移指南 如何用 C# 从 SSRS 迁移到 IronPDF Curtis Chau 已发布:2026年2月1日 下载 IronPDF NuGet 下载 DLL 下载 Windows 安装程序 免费试用 法学硕士副本 法学硕士副本 将页面复制为 Markdown 格式,用于 LLMs 在 ChatGPT 中打开 向 ChatGPT 咨询此页面 在双子座打开 向 Gemini 询问此页面 在 Grok 中打开 向 Grok 询问此页面 打开困惑 向 Perplexity 询问有关此页面的信息 分享 在 Facebook 上分享 分享到 X(Twitter) 在 LinkedIn 上分享 复制链接 电子邮件文章 从 SQL Server Reporting Services (SSRS) 迁移到IronPDF可将您的 PDF 生成工作流程从基于服务器的重量级基础架构转变为可直接嵌入任何 .NET 应用程序的轻量级进程内库。 本指南提供了一个完整的分步迁移路径,可消除 SQL Server 依赖性、报告服务器开销和微软生态系统锁定。 为什么要从SSRS迁移到 IronPDF. 了解 SSRS. SQL Server Reporting Services (SSRS) 是微软的企业报表平台,需要大量的基础设施投资。SSRS是微软公司推出的一个综合报表平台,提供了一套完整的报表创建、部署和管理工具,具有功能丰富的交互式报表功能。 作为 SQL Server 生态系统的一部分,SSRS 与 Microsoft 的数据库解决方案紧密集成。 然而,对于许多生成 PDF 的场景来说,SSRS 基础架构已经过剩。迁移的主要原因包括 1.基础设施要求高:需要 SQL Server、报表服务器和 IIS 配置 2.微软生态系统锁定:与 SQL Server 许可和Windows 服务器绑定 3.复杂部署:报表部署、安全配置和订阅管理 4.高昂的许可费用: SQL Server 许可费用,尤其是企业版功能许可费用。 Web 支持有限:难以与现代单页应用程序框架集成 6.维护成本:服务器补丁、数据库维护、报表管理 7.不支持云原生:专为本地部署而设计,云支持较为困难。 当SSRS矫枉过正时 您的需求 SSRS 开销 生成发票 完整的报告服务器 导出数据表 SQL Server 许可证 根据数据创建 PDF Windows 服务器 简单文档生成 报告订阅 IronPDF 提供进程内 PDF 生成功能,无需任何服务器基础设施。 SRS 与IronPDF对比 特征 SSRS IronPDF 依赖性 要求使用 SQL 服务器 不依赖特定数据库 部署 基于服务器 库(嵌入到应用程序中) 集成 与微软紧密集成 适用于任何数据源 数据可视化 广泛的本地选项 以 PDF 为重点的可视化 复杂性 高(需要服务器设置) 中低级(库设置) 成本 SQL Server 许可成本 每位开发人员的许可成本 HTML 到 PDF 否 完整的 Chromium URL 转 PDF 否 是 CSS支持 有限的 完整的 CSS3 JavaScript语言 否 完整的 ES2024 IronPDF 与SSRS不同,不与任何特定的数据库或服务器生态系统绑定。 它为开发人员提供了一个灵活的库,可直接在 C# 中动态创建、编辑和操作 PDF 文档。 这种与基于服务器的基础架构脱钩的方式具有明显的优势--它简单明了、适应性强,适用于报告以外的各种应用。 对于计划在 2025 年和 2026 年之前采用 .NET 10 和 C# 14 的团队,IronPDF 提供了现代化的 Chromium 渲染引擎,消除了SSRS基础设施的复杂性。 开始之前 前提条件 .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+ NuGet 访问权限:能够安装 NuGet 包 IronPDF 许可证:请从ironpdf.com获取您的许可证密钥。 NuGet 软件包变更 #SSRShas no direct NuGet - it's server-based # Remove any ReportViewer controls dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WebForms dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WinForms # Install IronPDF dotnet add package IronPdf #SSRShas no direct NuGet - it's server-based # Remove any ReportViewer controls dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WebForms dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WinForms # Install IronPDF dotnet add package IronPdf SHELL 许可配置 // Add at application startup IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"; // Add at application startup IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"; $vbLabelText $csharpLabel 完整的 API 参考 命名空间变更 // Before: SSRS using Microsoft.Reporting.WebForms; using Microsoft.Reporting.WinForms; // After: IronPDF using IronPdf; using IronPdf.Rendering; // Before: SSRS using Microsoft.Reporting.WebForms; using Microsoft.Reporting.WinForms; // After: IronPDF using IronPdf; using IronPdf.Rendering; $vbLabelText $csharpLabel 核心 API 映射 SSRS 概念 IronPdf 同等产品 备注 本地报告 ChromePdfRenderer 核心渲染 服务器报告 RenderUrlAsPdf() 基于 URL 的渲染 `.rdlc文件 HTML/CSS 模板 模板格式 报告参数 字符串插值 参数 ReportDataSource C# 数据 + HTML 数据绑定 LocalReport.Render("PDF") RenderHtmlAsPdf() PDF 输出 子报告 合并 PDF 嵌套报告 报告服务器 URL 不需要 无需服务器 ReportViewer控件 不需要 直接生成 PDF 导出格式 PDF 为本地格式 重点突出的产出 代码迁移示例 示例 1:HTML 到 PDF 的转换 之前 (SSRS): //SSRS- SQL Server Reporting Services using System; using System.Data; using System.Data.SqlClient; using Microsoft.Reporting.WebForms; using System.IO; class SSRSHtmlToPdf { static void Main() { // Create a ReportViewer instance var reportViewer = new ReportViewer(); reportViewer.ProcessingMode = ProcessingMode.Local; // Load RDLC report definition reportViewer.LocalReport.ReportPath = "Report.rdlc"; // Add HTML content as a parameter or dataset var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>"; var param = new ReportParameter("HtmlContent", htmlContent); reportViewer.LocalReport.SetParameters(param); // Render the report to PDF string mimeType, encoding, fileNameExtension; string[] streams; Warning[] warnings; byte[] bytes = reportViewer.LocalReport.Render( "PDF", null, out mimeType, out encoding, out fileNameExtension, out streams, out warnings); File.WriteAllBytes("output.pdf", bytes); } } //SSRS- SQL Server Reporting Services using System; using System.Data; using System.Data.SqlClient; using Microsoft.Reporting.WebForms; using System.IO; class SSRSHtmlToPdf { static void Main() { // Create a ReportViewer instance var reportViewer = new ReportViewer(); reportViewer.ProcessingMode = ProcessingMode.Local; // Load RDLC report definition reportViewer.LocalReport.ReportPath = "Report.rdlc"; // Add HTML content as a parameter or dataset var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>"; var param = new ReportParameter("HtmlContent", htmlContent); reportViewer.LocalReport.SetParameters(param); // Render the report to PDF string mimeType, encoding, fileNameExtension; string[] streams; Warning[] warnings; byte[] bytes = reportViewer.LocalReport.Render( "PDF", null, out mimeType, out encoding, out fileNameExtension, out streams, out warnings); File.WriteAllBytes("output.pdf", bytes); } } $vbLabelText $csharpLabel After (IronPDF): // NuGet: Install-Package IronPdf using IronPdf; using System; class IronPdfHtmlToPdf { static void Main() { // Create a ChromePdfRenderer instance var renderer = new ChromePdfRenderer(); // Convert HTML string to PDF var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>"; var pdf = renderer.RenderHtmlAsPdf(htmlContent); // Save the PDF file pdf.SaveAs("output.pdf"); } } // NuGet: Install-Package IronPdf using IronPdf; using System; class IronPdfHtmlToPdf { static void Main() { // Create a ChromePdfRenderer instance var renderer = new ChromePdfRenderer(); // Convert HTML string to PDF var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>"; var pdf = renderer.RenderHtmlAsPdf(htmlContent); // Save the PDF file pdf.SaveAs("output.pdf"); } } $vbLabelText $csharpLabel 本例展示了基本的架构差异。SSRS要求创建一个 ReportViewer 实例,加载一个 .rdlc 报告定义文件,设置参数,然后调用LocalReport.Render("PDF")并为元数据设置多个out` 参数。 IronPDF 使用ChromePdfRenderer与RenderHtmlAsPdf()仅三行代码。 不需要报告定义文件、参数对象和元数据处理。 请参阅 HTML 转 PDF 文档,了解全面的示例。 示例 2:带页眉和页脚的 URL 至 PDF 文件 之前 (SSRS): //SSRS- SQL Server Reporting Services using System; using System.IO; using System.Net; using Microsoft.Reporting.WebForms; class SSRSUrlToPdf { static void Main() { // Download HTML content from URL string url = "https://example.com"; string htmlContent; using (var client = new WebClient()) { htmlContent = client.DownloadString(url); } // Create RDLC report with header/footer configuration var reportViewer = new ReportViewer(); reportViewer.ProcessingMode = ProcessingMode.Local; reportViewer.LocalReport.ReportPath = "WebReport.rdlc"; // Set parameters for header and footer var parameters = new ReportParameter[] { new ReportParameter("HeaderText", "Company Report"), new ReportParameter("FooterText", "Page " + DateTime.Now.ToString()), new ReportParameter("HtmlContent", htmlContent) }; reportViewer.LocalReport.SetParameters(parameters); // Render to PDF string mimeType, encoding, fileNameExtension; string[] streams; Warning[] warnings; byte[] bytes = reportViewer.LocalReport.Render( "PDF", null, out mimeType, out encoding, out fileNameExtension, out streams, out warnings); File.WriteAllBytes("webpage.pdf", bytes); } } //SSRS- SQL Server Reporting Services using System; using System.IO; using System.Net; using Microsoft.Reporting.WebForms; class SSRSUrlToPdf { static void Main() { // Download HTML content from URL string url = "https://example.com"; string htmlContent; using (var client = new WebClient()) { htmlContent = client.DownloadString(url); } // Create RDLC report with header/footer configuration var reportViewer = new ReportViewer(); reportViewer.ProcessingMode = ProcessingMode.Local; reportViewer.LocalReport.ReportPath = "WebReport.rdlc"; // Set parameters for header and footer var parameters = new ReportParameter[] { new ReportParameter("HeaderText", "Company Report"), new ReportParameter("FooterText", "Page " + DateTime.Now.ToString()), new ReportParameter("HtmlContent", htmlContent) }; reportViewer.LocalReport.SetParameters(parameters); // Render to PDF string mimeType, encoding, fileNameExtension; string[] streams; Warning[] warnings; byte[] bytes = reportViewer.LocalReport.Render( "PDF", null, out mimeType, out encoding, out fileNameExtension, out streams, out warnings); File.WriteAllBytes("webpage.pdf", bytes); } } $vbLabelText $csharpLabel After (IronPDF): // NuGet: Install-Package IronPdf using IronPdf; using IronPdf.Rendering; using System; class IronPdfUrlToPdf { static void Main() { // Create a ChromePdfRenderer instance var renderer = new ChromePdfRenderer(); // Configure rendering options with header and footer renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>Company Report</div>" }; renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>Page {page} of {total-pages} - " + DateTime.Now.ToString("MM/dd/yyyy") + "</div>" }; // Convert URL to PDF string url = "https://example.com"; var pdf = renderer.RenderUrlAsPdf(url); // Save the PDF file pdf.SaveAs("webpage.pdf"); } } // NuGet: Install-Package IronPdf using IronPdf; using IronPdf.Rendering; using System; class IronPdfUrlToPdf { static void Main() { // Create a ChromePdfRenderer instance var renderer = new ChromePdfRenderer(); // Configure rendering options with header and footer renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>Company Report</div>" }; renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>Page {page} of {total-pages} - " + DateTime.Now.ToString("MM/dd/yyyy") + "</div>" }; // Convert URL to PDF string url = "https://example.com"; var pdf = renderer.RenderUrlAsPdf(url); // Save the PDF file pdf.SaveAs("webpage.pdf"); } } $vbLabelText $csharpLabel SSRS 无法直接将 URL 转换为 PDF。 您必须使用 WebClient.DownloadString() 手动下载 HTML 内容,创建单独的 .rdlc 报告文件,将 HTML 和页眉/页脚文本作为报告参数数组传递,然后使用复杂的 Render() 方法签名进行渲染。 IronPDF 的RenderUrlAsPdf()一次调用即可处理整个过程。 页眉和页脚使用 HtmlHeaderFooter 对象进行配置,该对象支持完整的 HTML/CSS 以及 {page} 和 {total-pages} 等占位符。 在我们的教程中了解更多信息。 示例 3:数据库驱动的报告 之前 (SSRS): //SSRS- SQL Server Reporting Services using System; using System.Data; using System.Data.SqlClient; using Microsoft.Reporting.WebForms; using System.IO; class SSRSDatabaseReport { static void Main() { // Create a ReportViewer instance var reportViewer = new ReportViewer(); reportViewer.ProcessingMode = ProcessingMode.Local; reportViewer.LocalReport.ReportPath = "SalesReport.rdlc"; // Create database connection and fetch data string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;"; using (var connection = new SqlConnection(connString)) { var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection); var dataSet = new DataSet(); adapter.Fill(dataSet, "Sales"); // Bind data to report var dataSource = new ReportDataSource("SalesDataSet", dataSet.Tables[0]); reportViewer.LocalReport.DataSources.Clear(); reportViewer.LocalReport.DataSources.Add(dataSource); } // Render to PDF string mimeType, encoding, fileNameExtension; string[] streams; Warning[] warnings; byte[] bytes = reportViewer.LocalReport.Render( "PDF", null, out mimeType, out encoding, out fileNameExtension, out streams, out warnings); File.WriteAllBytes("sales-report.pdf", bytes); } } //SSRS- SQL Server Reporting Services using System; using System.Data; using System.Data.SqlClient; using Microsoft.Reporting.WebForms; using System.IO; class SSRSDatabaseReport { static void Main() { // Create a ReportViewer instance var reportViewer = new ReportViewer(); reportViewer.ProcessingMode = ProcessingMode.Local; reportViewer.LocalReport.ReportPath = "SalesReport.rdlc"; // Create database connection and fetch data string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;"; using (var connection = new SqlConnection(connString)) { var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection); var dataSet = new DataSet(); adapter.Fill(dataSet, "Sales"); // Bind data to report var dataSource = new ReportDataSource("SalesDataSet", dataSet.Tables[0]); reportViewer.LocalReport.DataSources.Clear(); reportViewer.LocalReport.DataSources.Add(dataSource); } // Render to PDF string mimeType, encoding, fileNameExtension; string[] streams; Warning[] warnings; byte[] bytes = reportViewer.LocalReport.Render( "PDF", null, out mimeType, out encoding, out fileNameExtension, out streams, out warnings); File.WriteAllBytes("sales-report.pdf", bytes); } } $vbLabelText $csharpLabel After (IronPDF): // NuGet: Install-Package IronPdf using IronPdf; using System; using System.Data; using System.Data.SqlClient; using System.Text; class IronPdfDatabaseReport { static void Main() { // Create database connection and fetch data string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;"; var dataTable = new DataTable(); using (var connection = new SqlConnection(connString)) { var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection); adapter.Fill(dataTable); } // Build HTML table from data var htmlBuilder = new StringBuilder(); htmlBuilder.Append("<h1>Sales Report</h1><table border='1'><tr>"); foreach (DataColumn column in dataTable.Columns) htmlBuilder.Append($"<th>{column.ColumnName}</th>"); htmlBuilder.Append("</tr>"); foreach (DataRow row in dataTable.Rows) { htmlBuilder.Append("<tr>"); foreach (var item in row.ItemArray) htmlBuilder.Append($"<td>{item}</td>"); htmlBuilder.Append("</tr>"); } htmlBuilder.Append("</table>"); // Convert to PDF var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(htmlBuilder.ToString()); pdf.SaveAs("sales-report.pdf"); } } // NuGet: Install-Package IronPdf using IronPdf; using System; using System.Data; using System.Data.SqlClient; using System.Text; class IronPdfDatabaseReport { static void Main() { // Create database connection and fetch data string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;"; var dataTable = new DataTable(); using (var connection = new SqlConnection(connString)) { var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection); adapter.Fill(dataTable); } // Build HTML table from data var htmlBuilder = new StringBuilder(); htmlBuilder.Append("<h1>Sales Report</h1><table border='1'><tr>"); foreach (DataColumn column in dataTable.Columns) htmlBuilder.Append($"<th>{column.ColumnName}</th>"); htmlBuilder.Append("</tr>"); foreach (DataRow row in dataTable.Rows) { htmlBuilder.Append("<tr>"); foreach (var item in row.ItemArray) htmlBuilder.Append($"<td>{item}</td>"); htmlBuilder.Append("</tr>"); } htmlBuilder.Append("</table>"); // Convert to PDF var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf(htmlBuilder.ToString()); pdf.SaveAs("sales-report.pdf"); } } $vbLabelText $csharpLabel SSRS 需要一个预先设计好的 .rdlc 报告文件("SalesReport.rdlc"),填充一个 DataSet ,创建一个具有特定名称("SalesDataSet")且必须与报告定义相匹配的ReportDataSource,清除现有数据源,添加新数据源,然后进行渲染。 IronPDF 使用您现有的数据访问代码(相同的 SqlDataAdapter 模式),然后使用 StringBuilder 动态构建 HTML。 您可以完全控制使用标准 HTML/CSS 的布局,无需专有的报告定义文件。 功能对比 特征 SSRS IronPDF 基础设施 服务器要求 是(报告服务器) 否 SQL 服务器许可证 要求 不需要 Windows 服务器 要求 任何平台 数据库要求 是(ReportServer DB) 否 开发 视觉设计师 是 (.rdlc) HTML 编辑器 模板格式 RDLC/RDL HTML/CSS/Razor 数据来源 内置 DSN 任何 C# 数据 渲染 HTML 至 PDF 否 完整的 Chromium URL 至 PDF 否 是 CSS 支持 有限的 完整的 CSS3 JavaScript 否 完整的 ES2024 图表 内置 通过 JS 库 部署 报告部署 服务器 应用程序 配置 复杂 简单的 维护 高的 低 常见迁移问题 问题 1:RDLC 报告定义 SRS: 使用专有的 .rdlc XML 格式。 解决方案:转换为 HTML 模板: 1.在 Visual Studio 中打开 .rdlc 2.记录布局结构 3.在 HTML/CSS 中重新创建 4.使用 Razor 进行数据绑定 问题 2:共享数据源 SRS: Report Server 中的连接字符串。 解决方案:使用您应用程序的数据访问层: var data = await _dbContext.Sales.ToListAsync(); // Then bind to HTML template var data = await _dbContext.Sales.ToListAsync(); // Then bind to HTML template $vbLabelText $csharpLabel 问题 3:报告参数用户界面 SRS: 内置参数提示。 解决方案:在应用程序中构建参数用户界面: // Your own parameter form, then: var pdf = GenerateReport(startDate, endDate, region); // Your own parameter form, then: var pdf = GenerateReport(startDate, endDate, region); $vbLabelText $csharpLabel 第 4 期:订阅/计划报告 SRS: 内置订阅引擎。 解决方案:使用后台工作框架: // Using Hangfire or similar RecurringJob.AddOrUpdate("weekly-report", () => GenerateAndEmailReport(), Cron.Weekly); // Using Hangfire or similar RecurringJob.AddOrUpdate("weekly-report", () => GenerateAndEmailReport(), Cron.Weekly); $vbLabelText $csharpLabel 迁移清单 迁移前 清点所有SSRS报表( .rdlc文件) 文档数据源和连接 屏幕截图报告布局,供视觉参考 列出每个报表的报告参数 请注意订阅时间表 从ironpdf.com获取IronPDF许可证密钥 代码更新 删除 ReportViewer 包 安装IronPdf NuGet 包 将.rdlc文件转换为 HTML 模板 将LocalReport替换为ChromePdfRenderer 将ReportDataSource替换为 C# 数据 + HTML 模板 将ReportParameter替换为字符串插值 将LocalReport.Render("PDF")替换为RenderHtmlAsPdf() 使用HtmlHeaderFooter实现页眉/页脚 在应用程序启动时添加许可证初始化 基础设施 计划报告服务器停用 将订阅迁移到作业调度程序(例如 Hangfire) 更新部署脚本 测试 直观地比较 PDF 输出。 验证数据准确性 测试分页 检查所有参数 性能测试 Curtis Chau 立即与工程团队聊天 技术作家 Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。 相关文章 已发布2026年2月1日 如何用 C# 从 ZetPDF 迁移到 IronPDF 通过这本完整的 C# 指南,掌握从 ZetPDF 到 IronPDF 的迁移。从基于坐标的库转换到现代的 HTML 到 PDF 解决方案。包括 HTML 转换、合并 PDF 和移除 PDFSharp 依赖性的代码示例。 阅读更多 已发布2026年2月1日 如何用 C# 从 Scryber.Core 迁移到 IronPDF 通过这本完整的 C# 指南,掌握从 Scryber.Core 迁移到 IronPDF 的方法。从自定义 XML/HTML 解析转换到现代 Chromium 渲染器。包括 HTML 转换、URL 呈现和替换专有绑定的代码示例。 阅读更多 已发布2026年2月1日 如何用 C# 从 XFINIUM.PDF 迁移到 IronPDF 通过这本完整的 C# 指南,掌握从 XFINIUM.PDF 到 IronPDF 的迁移。从基于坐标的手动定位切换到声明式 HTML/CSS 渲染。包括替换图形基元和自动布局的代码示例。 阅读更多 如何用 C# 从 Sumatra PDF 迁移到 IronPDF如何用 C# 从 Spire.PDF 迁移...
已发布2026年2月1日 如何用 C# 从 ZetPDF 迁移到 IronPDF 通过这本完整的 C# 指南,掌握从 ZetPDF 到 IronPDF 的迁移。从基于坐标的库转换到现代的 HTML 到 PDF 解决方案。包括 HTML 转换、合并 PDF 和移除 PDFSharp 依赖性的代码示例。 阅读更多
已发布2026年2月1日 如何用 C# 从 Scryber.Core 迁移到 IronPDF 通过这本完整的 C# 指南,掌握从 Scryber.Core 迁移到 IronPDF 的方法。从自定义 XML/HTML 解析转换到现代 Chromium 渲染器。包括 HTML 转换、URL 呈现和替换专有绑定的代码示例。 阅读更多
已发布2026年2月1日 如何用 C# 从 XFINIUM.PDF 迁移到 IronPDF 通过这本完整的 C# 指南,掌握从 XFINIUM.PDF 到 IronPDF 的迁移。从基于坐标的手动定位切换到声明式 HTML/CSS 渲染。包括替换图形基元和自动布局的代码示例。 阅读更多