如何在PDF中绘制线条和矩形
Adobe PDF Library SDK (APDFL) 由 Datalogics 根据 Adobe 的许可进行分发,并与 Acrobat 引擎共享核心源代码。虽然功能强大,但其销售主导的定价模式、本机运行时占用、没有内置 HTML 转 PDF 渲染器,以及低级 API 设计导致许多 .NET 团队寻找替代方案。 本指南提供了从Adobe PDF 库 SDK到IronPDF的分步迁移路径——这是一个现代的 .NET PDF 库,支持 .NET Framework 4.6.2 到 .NET 9。
为什么要考虑放弃 Adobe PDF Library SDK?
虽然 APDFL 提供了基于 Acrobat 的 PDF 引擎,但一些因素使开发团队探索 HTML 到 PDF、文档操作和报表生成的替代方案。
销售主导,自定义定价
Datalogics 不会发布 APDFL 的价格列表。 根据 Datalogics 的定价页面,内部使用计划从约 $5,999/年起,OEM、ISV 和 SaaS 部署协商每平台费用外加版税或收入分成。总成本通常超出中小团队的能力,几乎总是需要进行销售对话。
复杂的本地 SDK 集成
APDFL 包裹一个与 Acrobat 分享渊源的本机 C/C++ 引擎。 .NET绑定 (Datalogics.PDFL) 需要特定平台的运行时二进制文件 — Adobe.PDF.Library.LM.NET NuGet包提供x64 Windows、Linux和macOS ARM负载 — 谨慎的内存管理,并且在每个入口点上有明确的Library生命周期。 这增加了开发开销并复杂化了 CI/CD 管道。
没有内置 HTML 渲染器
APDFL 的文档化转换列表涵盖了 PDF/A、PDF/X、ZUGFeRD、EPS、PS、XPS 和 Office 格式,但不包括 HTML。 用 APDFL 单独从 HTML 字符串制作 PDF 意味着手动构建页面、字体和内容流,或者与单独的 HTML 渲染引擎配对使用 APDFL。
低级 API 设计
using APDFL 创建 PDF 涉及以编程方式构建页面、内容流、文本运行和字体。 像渲染 HTML 字符串这样简单的任务变成了多步骤操作,涉及坐标计算、字体嵌入和手动内容元素管理。
库生命周期管理开销
每个入口点都需要用Library.Initialize() / Library.Terminate()调用)封装代码,并谨慎处理在内部创建的每个PDF对象。遗漏的清理会导致资源泄漏。
对于许多项目来说,过于繁重
对于主要需要 HTML 到 PDF 转换、基本文档操作或报告生成的应用程序,完整的基于 Acrobat 的引擎通常超过了工作负荷的要求。
Adobe PDF 库 SDK与 IronPDF:主要区别
了解这些库之间的基本架构差异有助于规划有效的迁移策略。
| 方面 | Adobe PDF 库 SDK | IronPDF | |
|---|---|---|---|
| 定价 | 销售主导; 内部使用从 ~$5,999/年起,OEM/SaaS 收取版税 | 每开发者 / 每部署 透明 | |
| 安装 | Adobe.PDF.Library.LM.NET 提供每个平台的本地运行时 |
简单的 NuGet 软件包 | |
| 文档创建 | 低级页面/内容构建 | HTML/CSS 渲染 | |
| HTML 到 PDF | 非内置 | ChromePdfRenderer.RenderHtmlAsPdf |
|
| 初始化 | using (Library lib = new Library()) 必需 |
自动翻译 | |
| 坐标系 | PostScript 点,左下方原点 | 基于 CSS 的布局 | |
| 字体处理 | 需要手动嵌入 | 自动翻译 | |
| 内存管理 | 手动清理每个 PDF 对象 | 标准 IDisposable 模式 | |
| 支持同步 | 不可用 | 完全支持Async/Await |
迁移前准备
前提条件
在开始迁移之前,请确保您的环境符合这些要求:
- .NET Framework 4.6.2+ 或 .NET Core 3.1 / .NET 5-9
- Visual Studio 2019+ 或 JetBrains Rider
- 访问 NuGet 包管理器 -IronPDF许可证密钥(可在ironpdf.com免费试用)
审核 Adobe PDF 库 SDK 使用情况
在您的解决方案目录中运行这些命令,以识别所有Adobe PDF 库 SDK引用:
grep -r "using Datalogics" --include="*.cs" .
grep -r "Adobe.PDF.Library" --include="*.csproj" .
grep -r "Library.Initialize\|Library.Terminate" --include="*.cs" .
grep -r "using Datalogics" --include="*.cs" .
grep -r "Adobe.PDF.Library" --include="*.csproj" .
grep -r "Library.Initialize\|Library.Terminate" --include="*.cs" .
值得期待的重大变化
| 翻译类别 | Adobe PDF 库 SDK | IronPDF | 迁移行动 |
|---|---|---|---|
| 初始化 | Library.Initialize() / Terminate() |
自动翻译 | 删除生命周期代码 |
| 文件创建 | new Document() 与页面构建 |
ChromePdfRenderer |
使用 HTML 渲染 |
| 坐标系 | PostScript 点,左下方原点 | 基于 CSS 的布局 | 使用 HTML/CSS |
| 字体处理 | 手动Font创建和嵌入 |
自动翻译 | 删除字体代码 |
| 内存管理 | 手动处理 COM 对象 | 标准 IDisposable | 使用using语句 |
| 页面构建 | CreatePage(), AddContent() |
从 HTML 自动生成 | 大幅简化 |
逐步迁移过程
步骤 1:更新 NuGet 软件包
移除Adobe PDF 库 SDK软件包并安装 IronPDF:
# Remove Adobe PDF Library (.NET 6/7/8 projects)
dotnet remove package Adobe.PDF.Library.LM.NET
# .NET Framework projects use the LM.NETFramework variant
dotnet remove package Adobe.PDF.Library.LM.NETFramework
# Install IronPDF
dotnet add package IronPdf
# Remove Adobe PDF Library (.NET 6/7/8 projects)
dotnet remove package Adobe.PDF.Library.LM.NET
# .NET Framework projects use the LM.NETFramework variant
dotnet remove package Adobe.PDF.Library.LM.NETFramework
# Install IronPDF
dotnet add package IronPdf
步骤 2:配置许可证密钥
用IronPDF基于代码的许可密钥取代 Adobe 的许可方式:
// Replace Adobe's Library.LicenseKey withIronPDFlicense
// Add at application startup, before anyIronPDFoperations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Verify license status
bool isLicensed = IronPdf.License.IsLicensed;
// Replace Adobe's Library.LicenseKey withIronPDFlicense
// Add at application startup, before anyIronPDFoperations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Verify license status
bool isLicensed = IronPdf.License.IsLicensed;
' Replace Adobe's Library.LicenseKey with IronPDF license
' Add at application startup, before any IronPDF operations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
' Verify license status
Dim isLicensed As Boolean = IronPdf.License.IsLicensed
步骤 3:更新命名空间引用
在解决方案中执行全局查找和替换:
| 查找 | 替换为 |
|---|---|
using Datalogics.PDFL; |
using IronPdf; |
APDFL公开一个根命名空间,Datalogics.PDFL。 using指令。
步骤 4:删除库生命周期代码
最重要的简化之一是删除初始化和终止模式:
//Adobe PDF 库 SDK- REMOVE THIS PATTERN
Library.Initialize();
try
{
// PDF operations
}
finally
{
Library.Terminate(); // Must always terminate
}
//IronPDF- Just use directly
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
//Adobe PDF 库 SDK- REMOVE THIS PATTERN
Library.Initialize();
try
{
// PDF operations
}
finally
{
Library.Terminate(); // Must always terminate
}
//IronPDF- Just use directly
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
Imports IronPdf
'Adobe PDF 库 SDK- REMOVE THIS PATTERN
Library.Initialize()
Try
' PDF operations
Finally
Library.Terminate() ' Must always terminate
End Try
'IronPDF- Just use directly
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
完整的 API 迁移参考
库生命周期方法
| Adobe 方法 | IronPDF 同等产品 |
|---|---|
Library.Initialize() |
不需要 |
Library.Terminate() |
不需要 |
Library.LicenseKey = "KEY" |
IronPdf.License.LicenseKey = "KEY" |
using (Library lib = new Library()) |
不需要 |
文档创建方法
| Adobe 方法 | IronPDF 方法 |
|---|---|
new Document() |
new ChromePdfRenderer() |
new Document(path) |
PdfDocument.FromFile(path) |
doc.CreatePage(index, rect) |
从 HTML 自动生成 |
doc.Save(SaveFlags.Full, path) |
pdf.SaveAs(path) |
doc.NumPages |
pdf.PageCount |
doc.GetPage(index) |
pdf.Pages[index] |
doc.InsertPages(insertAfter, src, start, count, flags) |
PdfDocument.Merge(pdfs) |
内容创建(重大范式转变)
Adobe PDF Library SDK 需要构建底层内容。IronPDF使用 HTML/CSS:
| Adobe 方法 | IronPDF 方法 |
|---|---|
new Text() |
使用HTML <h1>等。 |
text.AddRun(textRun) |
使用 HTML |
new TextRun(text, font, size, point) |
CSS 定型 |
new Font(name, flags) |
CSS font-family |
new Image(path) |
HTML <img> 标签 |
content.AddElement(...) |
HTML 内容 |
page.UpdateContent() |
不需要 |
水印和安全方法
| Adobe 方法 | IronPDF 方法 |
|---|---|
doc.Watermark(textParams, wmParams) |
pdf.ApplyWatermark(html) |
WatermarkParams.Opacity (0.0-1.0) |
opacity 参数 (0-100) 或 CSS opacity |
new EncryptionHandler(user, owner, perms) |
pdf.SecuritySettings |
PermissionFlags.PrintDoc |
AllowUserPrinting |
文本提取
| Adobe 方法 | IronPDF 方法 |
|---|---|
new WordFinder(doc, config) |
pdf.ExtractAllText() |
wordFinder.GetWordList() |
pdf.Pages[i].Text |
| 复杂的单词/字符迭代 | 单一方法调用 |
代码迁移示例
HTML 到 PDF 转换
APDFL 没有内置 HTML 渲染器。 最接近的一对一替代是手动构建页面和内容以模仿 HTML 文档将产生的布局,或将 APDFL 与一个独立的 HTML 到 PDF 引擎配对。
Adobe PDF 库 SDK 实现:
//Adobe PDF 库 SDK(Datalogics APDFL)
// NuGet: Adobe.PDF.Library.LM.NET — namespace Datalogics.PDFL
using Datalogics.PDFL;
using System;
class AdobeHtmlToPdf
{
static void Main()
{
using (Library lib = new Library())
using (Document doc = new Document())
{
// US Letter in points (8.5 x 11 inches @ 72 DPI)
Rect pageRect = new Rect(0, 0, 612, 792);
using (Page page = doc.CreatePage(Document.BeforeFirstPage, pageRect))
{
Content content = page.Content;
Font font = new Font("Helvetica", FontCreateFlags.Embedded);
Text text = new Text();
text.AddRun(new TextRun("Hello World", font, 24, new Point(72, 720)));
content.AddElement(text);
page.UpdateContent();
}
doc.Save(SaveFlags.Full, "output.pdf");
}
}
}
//Adobe PDF 库 SDK(Datalogics APDFL)
// NuGet: Adobe.PDF.Library.LM.NET — namespace Datalogics.PDFL
using Datalogics.PDFL;
using System;
class AdobeHtmlToPdf
{
static void Main()
{
using (Library lib = new Library())
using (Document doc = new Document())
{
// US Letter in points (8.5 x 11 inches @ 72 DPI)
Rect pageRect = new Rect(0, 0, 612, 792);
using (Page page = doc.CreatePage(Document.BeforeFirstPage, pageRect))
{
Content content = page.Content;
Font font = new Font("Helvetica", FontCreateFlags.Embedded);
Text text = new Text();
text.AddRun(new TextRun("Hello World", font, 24, new Point(72, 720)));
content.AddElement(text);
page.UpdateContent();
}
doc.Save(SaveFlags.Full, "output.pdf");
}
}
}
Imports Datalogics.PDFL
Imports System
Class AdobeHtmlToPdf
Shared Sub Main()
Using lib As New Library()
Using doc As New Document()
' US Letter in points (8.5 x 11 inches @ 72 DPI)
Dim pageRect As New Rect(0, 0, 612, 792)
Using page As Page = doc.CreatePage(Document.BeforeFirstPage, pageRect)
Dim content As Content = page.Content
Dim font As New Font("Helvetica", FontCreateFlags.Embedded)
Dim text As New Text()
text.AddRun(New TextRun("Hello World", font, 24, New Point(72, 720)))
content.AddElement(text)
page.UpdateContent()
End Using
doc.Save(SaveFlags.Full, "output.pdf")
End Using
End Using
End Sub
End Class
IronPDF 实现:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfHtmlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
// Convert HTML to PDF with simple API
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfHtmlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
// Convert HTML to PDF with simple API
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Imports System
Class IronPdfHtmlToPdf
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim htmlContent As String = "<html><body><h1>Hello World</h1></body></html>"
' Convert HTML to PDF with simple API
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
End Sub
End Class
IronPDF 消除了库生命周期包装器、转换参数对象和显式处置。 ChromePdfRenderer 使用基于Chromium的引擎来支持像素完美的CSS和JavaScript。 有关高级场景,请参阅 HTML 转 PDF 文档。
合并多个 PDF 文件
PDF 合并清楚地展示了 API 复杂性的差异。
Adobe PDF 库 SDK 实现:
//Adobe PDF 库 SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;
class AdobeMergePdfs
{
static void Main()
{
using (Library lib = new Library())
using (Document doc1 = new Document("document1.pdf"))
using (Document doc2 = new Document("document2.pdf"))
{
// InsertPages(insertAfter, sourceDoc, sourceStartPage, pageCount, flags)
doc1.InsertPages(
Document.LastPage,
doc2,
0,
Document.AllPages,
PageInsertFlags.Bookmarks | PageInsertFlags.Threads);
doc1.Save(SaveFlags.Full, "merged.pdf");
}
}
}
//Adobe PDF 库 SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;
class AdobeMergePdfs
{
static void Main()
{
using (Library lib = new Library())
using (Document doc1 = new Document("document1.pdf"))
using (Document doc2 = new Document("document2.pdf"))
{
// InsertPages(insertAfter, sourceDoc, sourceStartPage, pageCount, flags)
doc1.InsertPages(
Document.LastPage,
doc2,
0,
Document.AllPages,
PageInsertFlags.Bookmarks | PageInsertFlags.Threads);
doc1.Save(SaveFlags.Full, "merged.pdf");
}
}
}
Imports Datalogics.PDFL
Imports System
Class AdobeMergePdfs
Shared Sub Main()
Using lib As New Library()
Using doc1 As New Document("document1.pdf")
Using doc2 As New Document("document2.pdf")
' InsertPages(insertAfter, sourceDoc, sourceStartPage, pageCount, flags)
doc1.InsertPages(Document.LastPage, doc2, 0, Document.AllPages, PageInsertFlags.Bookmarks Or PageInsertFlags.Threads)
doc1.Save(SaveFlags.Full, "merged.pdf")
End Using
End Using
End Using
End Sub
End Class
IronPDF 实现:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfMergePdfs
{
static void Main()
{
// Load PDF documents
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
// Merge PDFs with simple method
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfMergePdfs
{
static void Main()
{
// Load PDF documents
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
// Merge PDFs with simple method
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
}
}
Imports IronPdf
Imports System
Class IronPdfMergePdfs
Shared Sub Main()
' Load PDF documents
Dim pdf1 = PdfDocument.FromFile("document1.pdf")
Dim pdf2 = PdfDocument.FromFile("document2.pdf")
' Merge PDFs with simple method
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("merged.pdf")
End Sub
End Class
Adobe 的方法要求使用插入参数逐页迭代。 IronPDF提供一个接受多个文档的单一Merge方法。
添加水印
水印说明了IronPDF如何利用 HTML/CSS 实现灵活的样式设计。
Adobe PDF 库 SDK 实现:
//Adobe PDF 库 SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;
class AdobeAddWatermark
{
static void Main()
{
using (Library lib = new Library())
using (Document doc = new Document("input.pdf"))
{
WatermarkParams watermarkParams = new WatermarkParams();
watermarkParams.Opacity = 0.5; // 0.0 - 1.0
watermarkParams.Rotation = 45.0;
watermarkParams.Scale = -1; // auto-fit
WatermarkTextParams textParams = new WatermarkTextParams();
textParams.Text = "CONFIDENTIAL";
textParams.Color = new Color(0.8, 0.8, 0.8);
textParams.TextAlign = HorizontalAlignment.Center;
// Apply via Document.Watermark(textParams, wmParams)
doc.Watermark(textParams, watermarkParams);
doc.Save(SaveFlags.Full, "watermarked.pdf");
}
}
}
//Adobe PDF 库 SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;
class AdobeAddWatermark
{
static void Main()
{
using (Library lib = new Library())
using (Document doc = new Document("input.pdf"))
{
WatermarkParams watermarkParams = new WatermarkParams();
watermarkParams.Opacity = 0.5; // 0.0 - 1.0
watermarkParams.Rotation = 45.0;
watermarkParams.Scale = -1; // auto-fit
WatermarkTextParams textParams = new WatermarkTextParams();
textParams.Text = "CONFIDENTIAL";
textParams.Color = new Color(0.8, 0.8, 0.8);
textParams.TextAlign = HorizontalAlignment.Center;
// Apply via Document.Watermark(textParams, wmParams)
doc.Watermark(textParams, watermarkParams);
doc.Save(SaveFlags.Full, "watermarked.pdf");
}
}
}
Imports Datalogics.PDFL
Imports System
Class AdobeAddWatermark
Shared Sub Main()
Using lib As New Library()
Using doc As New Document("input.pdf")
Dim watermarkParams As New WatermarkParams()
watermarkParams.Opacity = 0.5 ' 0.0 - 1.0
watermarkParams.Rotation = 45.0
watermarkParams.Scale = -1 ' auto-fit
Dim textParams As New WatermarkTextParams()
textParams.Text = "CONFIDENTIAL"
textParams.Color = New Color(0.8, 0.8, 0.8)
textParams.TextAlign = HorizontalAlignment.Center
' Apply via Document.Watermark(textParams, wmParams)
doc.Watermark(textParams, watermarkParams)
doc.Save(SaveFlags.Full, "watermarked.pdf")
End Using
End Using
End Sub
End Class
IronPDF 实现:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Editing;
using System;
class IronPdfAddWatermark
{
static void Main()
{
var pdf = PdfDocument.FromFile("input.pdf");
// Apply text watermark with simple API
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.5;'>CONFIDENTIAL</h1>",
rotation: 45,
verticalAlignment: VerticalAlignment.Middle,
horizontalAlignment: HorizontalAlignment.Center);
pdf.SaveAs("watermarked.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Editing;
using System;
class IronPdfAddWatermark
{
static void Main()
{
var pdf = PdfDocument.FromFile("input.pdf");
// Apply text watermark with simple API
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.5;'>CONFIDENTIAL</h1>",
rotation: 45,
verticalAlignment: VerticalAlignment.Middle,
horizontalAlignment: HorizontalAlignment.Center);
pdf.SaveAs("watermarked.pdf");
}
}
Imports IronPdf
Imports IronPdf.Editing
Imports System
Class IronPdfAddWatermark
Shared Sub Main()
Dim pdf = PdfDocument.FromFile("input.pdf")
' Apply text watermark with simple API
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.5;'>CONFIDENTIAL</h1>",
rotation:=45,
verticalAlignment:=VerticalAlignment.Middle,
horizontalAlignment:=HorizontalAlignment.Center)
pdf.SaveAs("watermarked.pdf")
End Sub
End Class
IronPDF 基于 HTML 的水印通过 CSS 样式提供完整的设计控制,无需单独的参数对象。
密码保护和加密
Adobe PDF 库 SDK 实现:
using Datalogics.PDFL;
public void ProtectPdf(string inputPath, string outputPath, string password)
{
Library.Initialize();
try
{
using (Document doc = new Document(inputPath))
{
PermissionFlags permissions =
PermissionFlags.PrintDoc |
PermissionFlags.PrintFidelity;
EncryptionHandler encHandler = new EncryptionHandler(
password, // User password
password, // Owner password
permissions,
EncryptionMethod.AES256);
doc.SetEncryptionHandler(encHandler);
doc.Save(SaveFlags.Full | SaveFlags.Encrypted, outputPath);
}
}
finally
{
Library.Terminate();
}
}
using Datalogics.PDFL;
public void ProtectPdf(string inputPath, string outputPath, string password)
{
Library.Initialize();
try
{
using (Document doc = new Document(inputPath))
{
PermissionFlags permissions =
PermissionFlags.PrintDoc |
PermissionFlags.PrintFidelity;
EncryptionHandler encHandler = new EncryptionHandler(
password, // User password
password, // Owner password
permissions,
EncryptionMethod.AES256);
doc.SetEncryptionHandler(encHandler);
doc.Save(SaveFlags.Full | SaveFlags.Encrypted, outputPath);
}
}
finally
{
Library.Terminate();
}
}
Imports Datalogics.PDFL
Public Sub ProtectPdf(inputPath As String, outputPath As String, password As String)
Library.Initialize()
Try
Using doc As New Document(inputPath)
Dim permissions As PermissionFlags = PermissionFlags.PrintDoc Or PermissionFlags.PrintFidelity
Dim encHandler As New EncryptionHandler(
password, ' User password
password, ' Owner password
permissions,
EncryptionMethod.AES256)
doc.SetEncryptionHandler(encHandler)
doc.Save(SaveFlags.Full Or SaveFlags.Encrypted, outputPath)
End Using
Finally
Library.Terminate()
End Try
End Sub
IronPDF 实现:
using IronPdf;
public void ProtectPdf(string inputPath, string outputPath, string password)
{
using var pdf = PdfDocument.FromFile(inputPath);
pdf.SecuritySettings.UserPassword = password;
pdf.SecuritySettings.OwnerPassword = password;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;
pdf.SaveAs(outputPath);
}
using IronPdf;
public void ProtectPdf(string inputPath, string outputPath, string password)
{
using var pdf = PdfDocument.FromFile(inputPath);
pdf.SecuritySettings.UserPassword = password;
pdf.SecuritySettings.OwnerPassword = password;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;
pdf.SaveAs(outputPath);
}
Imports IronPdf
Public Sub ProtectPdf(inputPath As String, outputPath As String, password As String)
Using pdf = PdfDocument.FromFile(inputPath)
pdf.SecuritySettings.UserPassword = password
pdf.SecuritySettings.OwnerPassword = password
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit
pdf.SaveAs(outputPath)
End Using
End Sub
IronPDF 使用强类型属性代替位操作权限标志和加密处理程序对象。
文本提取
Adobe PDF 库 SDK 实现:
using Datalogics.PDFL;
public string ExtractText(string pdfPath)
{
string extractedText = "";
Library.Initialize();
try
{
using (Document doc = new Document(pdfPath))
{
WordFinderConfig config = new WordFinderConfig();
config.IgnoreCharGaps = true;
for (int i = 0; i < doc.NumPages; i++)
{
using (WordFinder wordFinder = new WordFinder(doc, i, config))
{
IList<Word> words = wordFinder.GetWordList();
foreach (Word word in words)
{
extractedText += word.Text + " ";
}
extractedText += "\n";
}
}
}
}
finally
{
Library.Terminate();
}
return extractedText;
}
using Datalogics.PDFL;
public string ExtractText(string pdfPath)
{
string extractedText = "";
Library.Initialize();
try
{
using (Document doc = new Document(pdfPath))
{
WordFinderConfig config = new WordFinderConfig();
config.IgnoreCharGaps = true;
for (int i = 0; i < doc.NumPages; i++)
{
using (WordFinder wordFinder = new WordFinder(doc, i, config))
{
IList<Word> words = wordFinder.GetWordList();
foreach (Word word in words)
{
extractedText += word.Text + " ";
}
extractedText += "\n";
}
}
}
}
finally
{
Library.Terminate();
}
return extractedText;
}
Imports Datalogics.PDFL
Public Function ExtractText(ByVal pdfPath As String) As String
Dim extractedText As String = ""
Library.Initialize()
Try
Using doc As New Document(pdfPath)
Dim config As New WordFinderConfig()
config.IgnoreCharGaps = True
For i As Integer = 0 To doc.NumPages - 1
Using wordFinder As New WordFinder(doc, i, config)
Dim words As IList(Of Word) = wordFinder.GetWordList()
For Each word As Word In words
extractedText &= word.Text & " "
Next
extractedText &= vbLf
End Using
Next
End Using
Finally
Library.Terminate()
End Try
Return extractedText
End Function
IronPDF 实现:
using IronPdf;
public string ExtractText(string pdfPath)
{
using var pdf = PdfDocument.FromFile(pdfPath);
return pdf.ExtractAllText();
}
using IronPdf;
public string ExtractText(string pdfPath)
{
using var pdf = PdfDocument.FromFile(pdfPath);
return pdf.ExtractAllText();
}
Imports IronPdf
Public Function ExtractText(pdfPath As String) As String
Using pdf = PdfDocument.FromFile(pdfPath)
Return pdf.ExtractAllText()
End Using
End Function
Adobe 的逐字迭代通过IronPDF变成了单一的方法调用。
页眉和页脚
Adobe PDF 库 SDK 实现:
using Datalogics.PDFL;
public void AddHeaderFooter(string inputPath, string outputPath)
{
Library.Initialize();
try
{
using (Document doc = new Document(inputPath))
{
Font font = new Font("Helvetica", FontCreateFlags.None);
for (int i = 0; i < doc.NumPages; i++)
{
using (Page page = doc.GetPage(i))
{
Content content = page.Content;
// Add header
Text header = new Text();
header.AddRun(new TextRun("Document Header",
font, 10, new Point(72, page.MediaBox.Top - 36)));
content.AddElement(header);
// Add footer with page number
Text footer = new Text();
footer.AddRun(new TextRun($"Page {i + 1} of {doc.NumPages}",
font, 10, new Point(72, 36)));
content.AddElement(footer);
page.UpdateContent();
}
}
doc.Save(SaveFlags.Full, outputPath);
}
}
finally
{
Library.Terminate();
}
}
using Datalogics.PDFL;
public void AddHeaderFooter(string inputPath, string outputPath)
{
Library.Initialize();
try
{
using (Document doc = new Document(inputPath))
{
Font font = new Font("Helvetica", FontCreateFlags.None);
for (int i = 0; i < doc.NumPages; i++)
{
using (Page page = doc.GetPage(i))
{
Content content = page.Content;
// Add header
Text header = new Text();
header.AddRun(new TextRun("Document Header",
font, 10, new Point(72, page.MediaBox.Top - 36)));
content.AddElement(header);
// Add footer with page number
Text footer = new Text();
footer.AddRun(new TextRun($"Page {i + 1} of {doc.NumPages}",
font, 10, new Point(72, 36)));
content.AddElement(footer);
page.UpdateContent();
}
}
doc.Save(SaveFlags.Full, outputPath);
}
}
finally
{
Library.Terminate();
}
}
Imports Datalogics.PDFL
Public Sub AddHeaderFooter(inputPath As String, outputPath As String)
Library.Initialize()
Try
Using doc As New Document(inputPath)
Dim font As New Font("Helvetica", FontCreateFlags.None)
For i As Integer = 0 To doc.NumPages - 1
Using page As Page = doc.GetPage(i)
Dim content As Content = page.Content
' Add header
Dim header As New Text()
header.AddRun(New TextRun("Document Header", font, 10, New Point(72, page.MediaBox.Top - 36)))
content.AddElement(header)
' Add footer with page number
Dim footer As New Text()
footer.AddRun(New TextRun($"Page {i + 1} of {doc.NumPages}", font, 10, New Point(72, 36)))
content.AddElement(footer)
page.UpdateContent()
End Using
Next
doc.Save(SaveFlags.Full, outputPath)
End Using
Finally
Library.Terminate()
End Try
End Sub
IronPDF 实现:
using IronPdf;
public void CreatePdfWithHeaderFooter(string html, string outputPath)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter
{
CenterText = "Document Header",
FontSize = 10,
FontFamily = "Helvetica"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
CenterText = "Page {page} of {total-pages}",
FontSize = 10,
FontFamily = "Helvetica"
};
using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
}
using IronPdf;
public void CreatePdfWithHeaderFooter(string html, string outputPath)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter
{
CenterText = "Document Header",
FontSize = 10,
FontFamily = "Helvetica"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
CenterText = "Page {page} of {total-pages}",
FontSize = 10,
FontFamily = "Helvetica"
};
using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
}
Imports IronPdf
Public Sub CreatePdfWithHeaderFooter(html As String, outputPath As String)
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader = New TextHeaderFooter With {
.CenterText = "Document Header",
.FontSize = 10,
.FontFamily = "Helvetica"
}
renderer.RenderingOptions.TextFooter = New TextHeaderFooter With {
.CenterText = "Page {page} of {total-pages}",
.FontSize = 10,
.FontFamily = "Helvetica"
}
Using pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(outputPath)
End Using
End Sub
IronPDF自动处理页面迭代,并支持像{total-pages}这样的占位符标记。 有关更高级的布局,请参阅页眉和页脚文档。
URL到PDF转换
Adobe PDF Library SDK 缺乏内置 URL 渲染功能。IronPDF提供本地支持:
using IronPdf;
public void ConvertUrlToPdf(string url, string outputPath)
{
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs(outputPath);
}
using IronPdf;
public void ConvertUrlToPdf(string url, string outputPath)
{
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs(outputPath);
}
Imports IronPdf
Public Sub ConvertUrlToPdf(url As String, outputPath As String)
Dim renderer As New ChromePdfRenderer()
Using pdf = renderer.RenderUrlAsPdf(url)
pdf.SaveAs(outputPath)
End Using
End Sub
有关完整的 URL 转换选项,请参阅 URL 转 PDF 文档。
ASP.NET Core 集成
Adobe PDF Library SDK 的静态初始化模式会与依赖注入产生摩擦。IronPDF可与现代 .NET 架构自然集成。
Adobe 模式(DI 存在问题):
public class AdobePdfService
{
public byte[] Generate(string content)
{
Library.Initialize();
try
{
//复杂文档construction...
return bytes;
}
finally
{
Library.Terminate();
}
}
}
public class AdobePdfService
{
public byte[] Generate(string content)
{
Library.Initialize();
try
{
//复杂文档construction...
return bytes;
}
finally
{
Library.Terminate();
}
}
}
Public Class AdobePdfService
Public Function Generate(content As String) As Byte()
Library.Initialize()
Try
'复杂文档construction...
Return bytes
Finally
Library.Terminate()
End Try
End Function
End Class
IronPDF 模式(DI-友好):
public interface IPdfService
{
Task<byte[]> GeneratePdfAsync(string html);
}
public class IronPdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public IronPdfService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
using var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
}
// Register in Program.cs (.NET 6+):
builder.Services.AddSingleton<IPdfService, IronPdfService>();
public interface IPdfService
{
Task<byte[]> GeneratePdfAsync(string html);
}
public class IronPdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public IronPdfService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
using var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
}
// Register in Program.cs (.NET 6+):
builder.Services.AddSingleton<IPdfService, IronPdfService>();
Imports System.Threading.Tasks
Public Interface IPdfService
Function GeneratePdfAsync(html As String) As Task(Of Byte())
End Interface
Public Class IronPdfService
Implements IPdfService
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer()
_renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
End Sub
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte()) Implements IPdfService.GeneratePdfAsync
Using pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Using
End Function
End Class
' Register in Program.vb (.NET 6+):
builder.Services.AddSingleton(Of IPdfService, IronPdfService)()
同步支持
Adobe PDF Library SDK 不支持异步操作。IronPDF提供可扩展网络应用程序所必需的全部Async/Await功能:
public async Task<IActionResult> GenerateReport()
{
var renderer = new ChromePdfRenderer();
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
}
public async Task<IActionResult> GenerateReport()
{
var renderer = new ChromePdfRenderer();
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc
Public Class ReportController
Inherits Controller
Public Async Function GenerateReport() As Task(Of IActionResult)
Dim renderer As New ChromePdfRenderer()
Using pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return File(pdf.BinaryData, "application/pdf")
End Using
End Function
End Class
性能优化
内存使用对比
| 情景 | Adobe PDF 库 SDK | IronPDF |
|---|---|---|
| 简单 PDF | ~100 MB | ~50 MB |
| 复杂文档 | ~200 MB | ~80 MB |
| 批量(100 份 PDF) | 高(本地内存) | ~100 MB |
优化技巧
重用渲染器实例:
// Good: Reuse renderer for batch operations
var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs($"output_{i}.pdf");
}
// Good: Reuse renderer for batch operations
var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs($"output_{i}.pdf");
}
' Good: Reuse renderer for batch operations
Dim renderer = New ChromePdfRenderer()
For Each html In htmlList
Using pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs($"output_{i}.pdf")
End Using
Next
在 Web 应用程序中使用 Async:
public async Task<IActionResult> GenerateReport()
{
var renderer = new ChromePdfRenderer();
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
}
public async Task<IActionResult> GenerateReport()
{
var renderer = new ChromePdfRenderer();
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc
Public Class ReportController
Inherits Controller
Public Async Function GenerateReport() As Task(Of IActionResult)
Dim renderer As New ChromePdfRenderer()
Using pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return File(pdf.BinaryData, "application/pdf")
End Using
End Function
End Class
常见迁移问题的故障排除
问题:基于坐标的定位不起作用
Adobe 使用 PostScript 点坐标。IronPDF使用 CSS 定位:
// Adobe: Point-based
new TextRun("Hello", font, 12, new Point(100, 700));
// IronPDF: CSS-based
string html = "<p style='position:absolute; left:100px; top:92px;'>Hello</p>";
// Adobe: Point-based
new TextRun("Hello", font, 12, new Point(100, 700));
// IronPDF: CSS-based
string html = "<p style='position:absolute; left:100px; top:92px;'>Hello</p>";
' Adobe: Point-based
New TextRun("Hello", font, 12, New Point(100, 700))
' IronPDF: CSS-based
Dim html As String = "<p style='position:absolute; left:100px; top:92px;'>Hello</p>"
问题:页面大小差异
Adobe 使用 PostScript 点。IronPDF使用枚举或自定义维度:
// Adobe: Points
Rect(0, 0, 612, 792) // Letter
// IronPDF: Enum or custom
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
// Or custom:
renderer.RenderingOptions.SetCustomPaperSizeInInches(8.5, 11);
// Adobe: Points
Rect(0, 0, 612, 792) // Letter
// IronPDF: Enum or custom
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
// Or custom:
renderer.RenderingOptions.SetCustomPaperSizeInInches(8.5, 11);
' Adobe: Points
Rect(0, 0, 612, 792) ' Letter
' IronPDF: Enum or custom
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
' Or custom:
renderer.RenderingOptions.SetCustomPaperSizeInInches(8.5, 11)
问题:未找到字体
Adobe 要求手动嵌入字体。IronPDF可自动处理字体:
// IronPDF: Use web fonts if needed
string html = @"
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
body { font-family: 'Roboto', sans-serif; }
</style>";
// IronPDF: Use web fonts if needed
string html = @"
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
body { font-family: 'Roboto', sans-serif; }
</style>";
' IronPDF: Use web fonts if needed
Dim html As String = "
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
body { font-family: 'Roboto', sans-serif; }
</style>"
问题:SaveFlags 不可用
Adobe 使用保存标志组合。IronPDF采用直接保存的方式:
// Adobe
doc.Save(SaveFlags.Full | SaveFlags.Incremental, path);
//IronPDF- full save is default
pdf.SaveAs(path);
// Adobe
doc.Save(SaveFlags.Full | SaveFlags.Incremental, path);
//IronPDF- full save is default
pdf.SaveAs(path);
迁移后核对表
完成代码迁移后,请验证以下内容:
- 运行所有现有的单元测试和集成测试
- 将 PDF 输出结果与以前的版本进行直观比较
- 在测试环境中测试所有 PDF 工作流程
- 验证许可是否正常工作 (
IronPdf.License.IsLicensed) - 与先前实现的性能基准测试
- 移除 Adobe 许可配置
- 更新 CI/CD 流水线依赖项
- 从项目中移除所有 Adobe PDF 库 DLL 文件
- 为您的开发团队记录新的模式
其他资源
从 APDFL 迁移到IronPDF可以简化典型的 .NET PDF 生成代码库,特别是对于主要需要 HTML 到 PDF 或文档操作而不是完整的 Acrobat 衍生功能的团队而言。 从低级页面构建转换为HTML/CSS渲染消除了大部分坐标计算、字体管理和Library生命周期处理代码,而且IronPDF的每位开发者透明许可通常比APDFL的销售主导、OEM/SaaS-版税模式更易于预算。

