跳至页脚内容
迁移指南

如何用 C# 从 Apryse PDF 迁移到 IronPDF

从Apryse PDF迁移到 IronPDF:完整的 C# 迁移指南

Apryse PDF(前身为 PDFTron)是一款优质的企业级 PDF SDK,以其全面的文档处理能力而著称。 然而,其溢价定价模式(每位开发人员每年超过 1,500 美元)、复杂的集成要求和 C++ 传统为寻求直接 PDF 功能的开发团队制造了障碍。 本综合指南提供了从Apryse PDF逐步迁移到IronPDF的路径--IronPDF for .NET 是一个本地 .NET PDF 库,具有现代 C# 习惯、更简单的集成和一次性永久许可。

为什么要从Apryse PDF迁移? 虽然Apryse PDF提供了强大的功能,但仍有一些因素促使开发团队寻求替代方案来满足其 PDF 生成需求。 ### 高级定价和订阅模式 Apryse PDF 的目标客户是企业客户,其定价可能会让中小型项目望而却步: |方面|Apryse PDF (PDFTron)|IronPDF| |--------|-----------------|---------| |**起始价格**|1,500+美元/开发人员/年(已报告)|一次性 749 美元(Lite)| |**许可模式**|年度订购|永久许可证| |**查看器许可**|单独额外费用|不适用(使用标准查看器)| |**服务器许可证**|要求企业定价|包含在许可证层级中| |**3年总成本**|每位开发人员 4 500 美元以上|一次性 749 美元| ### 集成的复杂性 Apryse PDF 的 C++ 传统带来了复杂性,影响了开发速度: | 特征 |Apryse PDF|IronPDF| |---------|--------|---------| |**设置**|模块路径、外部二进制文件|单个 NuGet 软件包| |**初始化**|`PDFNet.Initialize()` 带许可证|简单的属性分配| |**HTML 渲染**|需要外部 html2pdf 模块|内置 Chromium 引擎| |**API 风格**|C++ 遗产,复杂|现代 C# 惯例| |**依赖关系**|多个 DLL,特定平台|自带软件包| ### 何时考虑迁移 **迁移到 IronPDF,如果:** - 您主要需要将 HTML/URL 转换为 PDF - 您希望 API 更简单,模板更少 - 对于您的使用情况而言,高级定价并不合理 - 您不需要 PDFViewCtrl 浏览器控件 - 您更偏好一次性许可,而不是订阅 **如果出现以下情况,请继续使用 Apryse PDF:** - 您需要他们的本地查看器控件 (PDFViewCtrl) - 您广泛使用 XOD 或专有格式 - 您需要特定的企业功能(高级编辑等) - 您的组织已经拥有企业许可证 ## 迁移前准备 ### 前提条件 确保您的环境符合这些要求: - .NET Framework 4.6.2+ 或 .NET Core 3.1 / .NET 5-9 - Visual Studio 2019+ 或带有 C# 扩展的 VS Code - 访问 NuGet 包管理器 -IronPDF许可证密钥(可在[ironpdf.com](https://ironpdf.com/licensing/)免费试用) ### 审计Apryse PDF的使用 在解决方案目录中运行这些命令以识别所有 Apryse 引用: ```bash # Find all pdftron using statements grep -r "using pdftron" --include="*.cs" . # Find PDFNet initialization grep -r "PDFNet.Initialize\|PDFNet.SetResourcesPath" --include="*.cs" . # Find PDFDoc usage grep -r "new PDFDoc\|PDFDoc\." --include="*.cs" . # Find HTML2PDF usage grep -r "HTML2PDF\|InsertFromURL\|InsertFromHtmlString" --include="*.cs" . # Find ElementReader/Writer usage grep -r "ElementReader\|ElementWriter\|ElementBuilder" --include="*.cs" . ``` ### 值得期待的重大变化 |Apryse PDF 样式|更改要求| |----------------|-----------------| |<代码>PDFNet.Initialize()HTML2PDF模块|内置 `ChromePdfRenderer`| |<代码>元素读取器/<代码>元素写入器SDFDoc.SaveOptionsPDFViewCtrlPDFDocPDF 文档HTML2PDFChromePdfRenderer文本提取器PdfDocument.ExtractAllText()StamperPdfDocument.ApplyWatermark()PDFDrawPdfDocument.ToBitmap()安全处理程序PdfDocument.SecuritySettingsPDFNetIronPdf.Licensenew PDFDoc()new PdfDocument()new PDFDoc(path)PdfDocument.FromFile(路径)new PDFDoc(buffer)PdfDocument.FromBinaryData(字节)doc.Save(路径, 选项)pdf.SaveAs(路径)doc.Save(缓冲区)pdf.BinaryDatadoc.Close()pdf.Dispose()usingdoc.GetPageCount()pdf.PageCountdoc.AppendPages(doc2, start, end)PdfDocument.Merge(pdfs)HTML2PDF.Convert(doc)renderer.RenderHtmlAsPdf(html)converter.InsertFromURL(url)renderer.RenderUrlAsPdf(url)converter.InsertFromHtmlString(html)renderer.RenderHtmlAsPdf(html)converter.SetModulePath(路径)converter.SetPaperSize(宽度, 高度)RenderingOptions.PaperSizeconverter.SetLandscape(true)RenderingOptions.PaperOrientation

Hello World

Content here

"; using (PDFDoc doc = new PDFDoc()) { HTML2PDF converter = new HTML2PDF(); converter.SetModulePath("path/to/html2pdf"); converter.InsertFromHtmlString(html); HTML2PDF.WebPageSettings settings = new HTML2PDF.WebPageSettings(); settings.SetPrintBackground(true); settings.SetLoadImages(true); if (converter.Convert(doc)) { doc.Save("output.pdf", SDFDoc.SaveOptions.e_linearized); Console.WriteLine("PDF created successfully"); } else { Console.WriteLine($"Conversion failed: {converter.GetLog()}"); } } PDFNet.Terminate(); } } ``` **IronPDF 实现:** ```csharp // NuGet: Install-Package IronPdf using IronPdf; class Program { static void Main() { var renderer = new ChromePdfRenderer(); string html = "

Hello World

"; var pdf = renderer.RenderHtmlAsPdf(html); pdf.SaveAs("output.pdf"); } } ``` IronPdf 消除了初始化、模块路径和清理代码,将 35 行以上的代码减少到 5 行。 ### URL到PDF转换 **Apryse PDF 实现:** ```csharp using pdftron; using pdftron.PDF; PDFNet.Initialize("YOUR_LICENSE_KEY"); using (PDFDoc doc = new PDFDoc()) { HTML2PDF converter = new HTML2PDF(); converter.SetModulePath("path/to/html2pdf"); HTML2PDF.WebPageSettings settings = new HTML2PDF.WebPageSettings(); settings.SetLoadImages(true); settings.SetAllowJavaScript(true); settings.SetPrintBackground(true); converter.InsertFromURL("https://example.com", settings); if (converter.Convert(doc)) { doc.Save("webpage.pdf", SDFDoc.SaveOptions.e_linearized); } } PDFNet.Terminate(); ``` **IronPDF 实现:** ```csharp // NuGet: Install-Package IronPdf using IronPdf; class Program { static void Main() { var renderer = new ChromePdfRenderer(); string url = "https://www.example.com"; var pdf = renderer.RenderUrlAsPdf(url); pdf.SaveAs("webpage.pdf"); } } ``` ### 合并多个 PDF 文件 **Apryse PDF 实现:** ```csharp using pdftron; using pdftron.PDF; PDFNet.Initialize("YOUR_LICENSE_KEY"); using (PDFDoc mainDoc = new PDFDoc()) { string[] files = { "doc1.pdf", "doc2.pdf", "doc3.pdf" }; foreach (string file in files) { using (PDFDoc doc = new PDFDoc(file)) { mainDoc.AppendPages(doc, 1, doc.GetPageCount()); } } mainDoc.Save("merged.pdf", SDFDoc.SaveOptions.e_linearized); } PDFNet.Terminate(); ``` **IronPDF 实现:** ```csharp // NuGet: Install-Package IronPdf using IronPdf; using System.Collections.Generic; class Program { static void Main() { var pdf1 = PdfDocument.FromFile("document1.pdf"); var pdf2 = PdfDocument.FromFile("document2.pdf"); var merged = PdfDocument.Merge(new List { pdf1, pdf2 }); merged.SaveAs("merged.pdf"); } } ``` IronPdf 的静态 `Merge` 方法可直接接受多个文档,消除了页面迭代模式。 ### 文本提取 **Apryse PDF 实现:** ```csharp using pdftron; using pdftron.PDF; PDFNet.Initialize("YOUR_LICENSE_KEY"); using (PDFDoc doc = new PDFDoc("document.pdf")) { TextExtractor extractor = new TextExtractor(); for (int i = 1; i <= doc.GetPageCount(); i++) { Page page = doc.GetPage(i); extractor.Begin(page); string pageText = extractor.GetAsText(); Console.WriteLine($"Page {i}:"); Console.WriteLine(pageText); } } PDFNet.Terminate(); ``` **IronPDF 实现:** ```csharp using IronPdf; var pdf = PdfDocument.FromFile("document.pdf"); // Extract all text at once string allText = pdf.ExtractAllText(); Console.WriteLine(allText); // Extract from specific page string page1Text = pdf.ExtractTextFromPage(0); // 0-indexed Console.WriteLine($"Page 1: {page1Text}"); ``` ### 添加水印 **Apryse PDF 实现:** ```csharp using pdftron; using pdftron.PDF; PDFNet.Initialize("YOUR_LICENSE_KEY"); using (PDFDoc doc = new PDFDoc("document.pdf")) { Stamper stamper = new Stamper(Stamper.SizeType.e_relative_scale, 0.5, 0.5); stamper.SetAlignment(Stamper.HorizontalAlignment.e_horizontal_center, Stamper.VerticalAlignment.e_vertical_center); stamper.SetOpacity(0.3); stamper.SetRotation(45); stamper.SetFontColor(new ColorPt(1, 0, 0)); stamper.SetTextAlignment(Stamper.TextAlignment.e_align_center); stamper.StampText(doc, "CONFIDENTIAL", new PageSet(1, doc.GetPageCount())); doc.Save("watermarked.pdf", SDFDoc.SaveOptions.e_linearized); } PDFNet.Terminate(); ``` **IronPDF 实现:** ```csharp using IronPdf; using IronPdf.Editing; var pdf = PdfDocument.FromFile("document.pdf"); // HTML-based watermark with full styling control string watermarkHtml = @"
CONFIDENTIAL
"; pdf.ApplyWatermark(watermarkHtml, rotation: 45, verticalAlignment: VerticalAlignment.Middle, horizontalAlignment: HorizontalAlignment.Center); pdf.SaveAs("watermarked.pdf"); ``` IronPdf 使用[基于 HTML/CSS 的水印](https://ironpdf.com/how-to/backgrounds-and-foregrounds/),通过熟悉的网络技术提供全面的样式控制。 ### 密码保护 **Apryse PDF 实现:** ```csharp using pdftron; using pdftron.PDF; using pdftron.SDF; PDFNet.Initialize("YOUR_LICENSE_KEY"); using (PDFDoc doc = new PDFDoc("document.pdf")) { SecurityHandler handler = new SecurityHandler(); handler.ChangeUserPassword("user123"); handler.ChangeMasterPassword("owner456"); handler.SetPermission(SecurityHandler.Permission.e_print, false); handler.SetPermission(SecurityHandler.Permission.e_extract_content, false); doc.SetSecurityHandler(handler); doc.Save("protected.pdf", SDFDoc.SaveOptions.e_linearized); } PDFNet.Terminate(); ``` **IronPDF 实现:** ```csharp using IronPdf; var pdf = PdfDocument.FromFile("document.pdf"); // Set passwords pdf.SecuritySettings.UserPassword = "user123"; pdf.SecuritySettings.OwnerPassword = "owner456"; // Set permissions pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint; pdf.SecuritySettings.AllowUserCopyPasteContent = false; pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit; pdf.SaveAs("protected.pdf"); ``` ### 页眉和页脚 **IronPDF 实现:** ```csharp using IronPdf; var renderer = new ChromePdfRenderer(); renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter { HtmlFragment = "
Company Header
", DrawDividerLine = true, MaxHeight = 30 }; renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter { HtmlFragment = "
Page {page} of {total-pages}
", DrawDividerLine = true, MaxHeight = 25 }; var pdf = renderer.RenderHtmlAsPdf("

Content

"); pdf.SaveAs("with_headers.pdf"); ``` IronPdf 支持占位符标记,如用于动态页码的 `{page}` 和 `{total-pages}` 。 有关更多选项,请参阅[页眉和页脚文档](https://ironpdf.com/how-to/headers-and-footers/)。 ## ASP.NET Core 集成 Apryse PDF 的初始化要求使网络应用程序集成变得复杂。 IronPdf 简化了这种模式。 **IronPdf模式:** ```csharp [ApiController] [Route("[controller]")] public class PdfController : ControllerBase { [HttpGet("generate")] public IActionResult GeneratePdf() { var renderer = new ChromePdfRenderer(); var pdf = renderer.RenderHtmlAsPdf("

Report

"); return File(pdf.BinaryData, "application/pdf", "report.pdf"); } [HttpGet("generate-async")] public async Task GeneratePdfAsync() { var renderer = new ChromePdfRenderer(); var pdf = await renderer.RenderHtmlAsPdfAsync("

Report

"); return File(pdf.Stream, "application/pdf", "report.pdf"); } } ``` ### 依赖注入配置 ```csharp // Program.cs public void ConfigureServices(IServiceCollection services) { // Set license once IronPdf.License.LicenseKey = Configuration["IronPdf:LicenseKey"]; // Register renderer as scoped service services.AddScoped(); // Or create a wrapper service services.AddScoped(); } // IronPdfService.cs public class IronPdfService : IPdfService { private readonly ChromePdfRenderer _renderer; public IronPdfService() { _renderer = new ChromePdfRenderer(); _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4; _renderer.RenderingOptions.PrintHtmlBackgrounds = true; } public PdfDocument GenerateFromHtml(string html) => _renderer.RenderHtmlAsPdf(html); public Task GenerateFromHtmlAsync(string html) => _renderer.RenderHtmlAsPdfAsync(html); } ``` ## 性能比较 | 指标 |Apryse PDF|IronPDF| |--------|--------|---------| |**冷启动**|快速(本地代码)|~2s (Chromium init)| |**后续渲染**|快速|快速| |**复杂的 HTML**|变量(html2pdf 模块)|优秀(Chromium)| |**CSS 支持**。| 有限的 |完整的 CSS3| |**JavaScript**语言| 有限的 |全面支持| ### 性能优化技巧 ```csharp // 1. Reuse renderer instance private static readonly ChromePdfRenderer SharedRenderer = new ChromePdfRenderer(); // 2. Disable unnecessary features for speed var renderer = new ChromePdfRenderer(); renderer.RenderingOptions.EnableJavaScript = false; // If not needed renderer.RenderingOptions.WaitFor.RenderDelay(0); // No delay renderer.RenderingOptions.Timeout = 30000; // 30s max // 3. Proper disposal using (var pdf = renderer.RenderHtmlAsPdf(html)) { pdf.SaveAs("output.pdf"); } ``` ## 常见迁移问题的故障排除 ### 问题:模块路径错误 移除所有模块路径配置-IronPDF 的 Chromium 引擎是内置的: ```csharp // Remove this converter.SetModulePath("path/to/html2pdf"); // Just use the renderer var renderer = new ChromePdfRenderer(); ``` ### 问题:PDFNet.Initialize() 未找到 替换为 IronPdf 许可证设置: ```csharp // Remove this PDFNet.Initialize("KEY"); PDFNet.SetResourcesPath("path"); // Use this (optional for development) IronPdf.License.LicenseKey = "YOUR-KEY"; ``` ### 问题:PDFViewCtrl 替换 IronPdf 不包含查看器控件。 选项: - 使用 PDF.js 制作网络浏览器 - 使用系统 PDF 查看器 - 考虑使用第三方查看器组件 ## 迁移后核对表 完成代码迁移后,请验证以下内容: - [ ] 验证 PDF 输出质量是否符合预期 - [ ] 测试所有边缘情况(大型文档、复杂 CSS) - [ ] 比较性能指标 - [ ] 更新 Docker 配置(如适用 - [ ] 删除 Apryse 许可证和相关配置 - [ ] 记录 IronPdf 的任何特定配置 - [ ] 为团队提供有关新 API 模式的培训 - [ ] 必要时更新 CI/CD 管道 ## 未来保护您的 PDF 基础架构 .NET10即将推出,C# 14也将引入新的语言特性,因此选择具有现代约定的本地.NET PDF 库可以确保与不断发展的运行时功能兼容。IronPDFfor .NET 承诺支持最新的 .NET 版本,这意味着您的迁移投资将在项目扩展到 2025 年和 2026 年时获得回报--无需每年续订。 ## 其他资源 - [IronPDF文档](https://ironpdf.com/docs/) - [HTML转PDF教程](https://ironpdf.com/tutorials/) - [API Reference](https://ironpdf.com/object-reference/api/) - [NuGet软件包](https://www.nuget.org/packages/IronPdf/) - [许可选项](https://ironpdf.com/licensing/) --- 从Apryse PDF迁移到IronPDF可将您的 PDF 代码库从复杂的 C++ 模式转换为惯用的 C#。 消除初始化模板、模块路径配置和基于订阅的许可可立即提高生产率,同时降低长期成本。
Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。