如何用 C# 从 iText 迁移到 IronPDF
从 iText 迁移到IronPDF会将您的 .NET PDF 工作流程从需要手动构建 Paragraph、Table 和 Cell 对象的编程 API 转变为具有完整 CSS3 和JavaScript支持的现代 HTML 优先方法。 本指南提供了一个全面的、循序渐进的迁移路径,消除了 AGPL许可证的顾虑,也无需为专业的 .NET 开发人员单独安装 pdfHTML 附加组件。
为什么要从 iText 迁移到 IronPDF.
AGPL 许可陷阱
iText 给商业应用带来了严重的法律和商业风险,许多开发团队发现时已经为时已晚:
- AGPL 病毒式许可:如果您在 Web 应用程序中使用 iText,AGPL 要求您开源您的整个应用程序——不仅仅是 PDF 代码,而是您的整个代码库。 这对于大多数商业软件来说都是不可能的。
2.没有永久许可: iText 取消了永久许可,强制每年续订订阅,这增加了总拥有成本。
- pdfHTML 附加组件费用: HTML 转 PDF 功能需要 pdfHTML 附加组件,该组件需在基本许可证之外另行购买。
4.复杂的许可审计:企业部署面临许可的复杂性和审计风险,这可能会延误项目并造成法律风险。
5.仅程序 API: iText 需要使用 Paragraph、Table、Cell 对象手动构建底层 PDF——对于复杂的布局来说,这既繁琐又容易出错。
6.现代 Web 渲染有限:即使使用 pdfHTML,复杂的 CSS 和JavaScript内容也需要付出大量额外努力。
iText 与IronPDF对比
| 特征 | iText 7 / iTextSharp | IronPDF |
|---|---|---|
| 许可证 | AGPL(病毒式)或昂贵的订阅 | 商业、永久选项 |
| HTML 转 PDF | 单独的 pdfHTML 附加组件 | 内置 Chromium 渲染器 |
| CSS 支持 | 基本 CSS | 完全 CSS3、Flexbox、网格 |
| JavaScript | 无 | 全面执行 |
| 应用程序接口范例 | 程式化(段落、表格、单元格) | HTML 优先,带 CSS |
| 学习曲线 | 陡峭(PDF 坐标系) | 对网络开发人员友好 |
| 开源风险 | 必须是开源网络应用程序 | 无病毒要求 |
| 定价模式 | 仅限订阅 | 永久或订阅 |
对于计划在 2025 年和 2026 年之前采用 .NET 10 和 C# 14 的团队来说,IronPDF 提供了一个面向未来的基础,其 HTML 优先的方法可利用团队已有的网络开发技能。
迁移复杂性评估
按功能估算的工作量
| 特征 | 迁移复杂性 |
|---|---|
| HTML 至 PDF | 极低 |
| 合并 PDF | low |
| 文本和图片 | low |
| 表格 | 语言 |
| 页眉/页脚 | 语言 |
| 安全/加密 | low |
范式转换
iText此次迁移的根本转变是从程序化PDF构建转向HTML优先渲染:
iText: PdfWriter → PdfDocument → Document → Add(Paragraph) → Add(Table)
IronPDF: ChromePdfRenderer → RenderHtmlAsPdf(htmlString) → SaveAs()
这种模式的转变是一种解放:您无需学习 iText 的对象模型,而是使用网络开发人员已经掌握的 HTML 和 CSS 技能。
开始之前
前提条件
- .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet 访问权限:能够安装 NuGet 包
- IronPDF 许可证:请从ironpdf.com获取您的许可证密钥。
NuGet 软件包变更
# Remove iText packages
dotnet remove package itext7
dotnet remove package itext7.pdfhtml
dotnet remove package itextsharp
# Install IronPDF
dotnet add package IronPdf
# Remove iText packages
dotnet remove package itext7
dotnet remove package itext7.pdfhtml
dotnet remove package itextsharp
# Install IronPDF
dotnet add package IronPdf
许可配置
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
确定 iText 的用法
# Find all iText references
grep -r "using iText\|using iTextSharp" --include="*.cs" .
grep -r "PdfWriter\|PdfDocument\|Document\|Paragraph\|Table\|Cell" --include="*.cs" .
grep -r "HtmlConverter\|ConverterProperties" --include="*.cs" .
# Find all iText references
grep -r "using iText\|using iTextSharp" --include="*.cs" .
grep -r "PdfWriter\|PdfDocument\|Document\|Paragraph\|Table\|Cell" --include="*.cs" .
grep -r "HtmlConverter\|ConverterProperties" --include="*.cs" .
完整的 API 参考
类映射
| iText 7 类 | iTextSharp 类 | IronPDF 同等产品 |
|---|---|---|
PdfWriter |
PdfWriter |
ChromePdfRenderer |
PdfDocument |
Document |
PdfDocument |
Document |
Document |
ChromePdfRenderer.RenderHtmlAsPdf() |
Paragraph |
Paragraph |
HTML <p>, <h1> 等。 |
Table |
PdfPTable |
HTML <table> |
Cell |
PdfPCell |
HTML <td>, <th> |
Image |
Image |
HTML <img> |
PdfReader |
PdfReader |
PdfDocument.FromFile() |
PdfMerger |
不适用 | PdfDocument.Merge() |
命名空间映射
| iText 7 名称空间 | IronPDF 同等产品 |
|---|---|
iText.Kernel.Pdf |
IronPdf |
iText.Layout |
IronPdf |
iText.Layout.Element |
使用 HTML 元素 |
iText.Html2Pdf |
IronPdf(内置) |
iText.IO.Image |
使用 HTML <img> |
iText.Kernel.Utils |
IronPdf |
代码迁移示例
示例 1:HTML 到 PDF 的转换
之前(iText 7):
// NuGet: Install-Package itext7
using iText.Html2pdf;
using System.IO;
class Program
{
static void Main()
{
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
string outputPath = "output.pdf";
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
{
HtmlConverter.ConvertToPdf(html, fs);
}
}
}
// NuGet: Install-Package itext7
using iText.Html2pdf;
using System.IO;
class Program
{
static void Main()
{
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
string outputPath = "output.pdf";
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
{
HtmlConverter.ConvertToPdf(html, fs);
}
}
}
Imports iText.Html2pdf
Imports System.IO
Class Program
Shared Sub Main()
Dim html As String = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
Dim outputPath As String = "output.pdf"
Using fs As FileStream = New FileStream(outputPath, FileMode.Create)
HtmlConverter.ConvertToPdf(html, fs)
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html As String = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class
iText 方法需要单独的 iText.Html2pdf 包(pdfHTML 插件,单独出售),创建一个 FileStream,并将所有内容包装在 using 语句中以便正确处置。 HtmlConverter.ConvertToPdf() 方法直接写入流。
IronPDF 的方法更简洁:创建一个 ChromePdfRenderer,使用你的 HTML 字符串调用 RenderHtmlAsPdf(),然后对生成的 PdfDocument 调用 SaveAs()。 没有单独的软件包,没有流管理,Chromium 渲染引擎提供卓越的 CSS3 和JavaScript支持。 有关其他渲染选项,请参阅 HTML to PDF 文档。
示例 2:合并多个 PDF 文件
之前(iText 7):
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Kernel.Utils;
using System.IO;
class Program
{
static void Main()
{
string outputPath = "merged.pdf";
string[] inputFiles = { "document1.pdf", "document2.pdf", "document3.pdf" };
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdfDoc = new PdfDocument(writer))
{
PdfMerger merger = new PdfMerger(pdfDoc);
foreach (string file in inputFiles)
{
using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
{
merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
}
}
}
}
}
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Kernel.Utils;
using System.IO;
class Program
{
static void Main()
{
string outputPath = "merged.pdf";
string[] inputFiles = { "document1.pdf", "document2.pdf", "document3.pdf" };
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdfDoc = new PdfDocument(writer))
{
PdfMerger merger = new PdfMerger(pdfDoc);
foreach (string file in inputFiles)
{
using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
{
merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
}
}
}
}
}
Imports iText.Kernel.Pdf
Imports iText.Kernel.Utils
Imports System.IO
Class Program
Shared Sub Main()
Dim outputPath As String = "merged.pdf"
Dim inputFiles As String() = {"document1.pdf", "document2.pdf", "document3.pdf"}
Using writer As New PdfWriter(outputPath)
Using pdfDoc As New PdfDocument(writer)
Dim merger As New PdfMerger(pdfDoc)
For Each file As String In inputFiles
Using sourcePdf As New PdfDocument(New PdfReader(file))
merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages())
End Using
Next
End Using
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System.Collections.Generic;
class Program
{
static void Main()
{
var pdfDocuments = new List<PdfDocument>
{
PdfDocument.FromFile("document1.pdf"),
PdfDocument.FromFile("document2.pdf"),
PdfDocument.FromFile("document3.pdf")
};
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System.Collections.Generic;
class Program
{
static void Main()
{
var pdfDocuments = new List<PdfDocument>
{
PdfDocument.FromFile("document1.pdf"),
PdfDocument.FromFile("document2.pdf"),
PdfDocument.FromFile("document3.pdf")
};
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
}
}
Imports IronPdf
Imports System.Collections.Generic
Class Program
Shared Sub Main()
Dim pdfDocuments As New List(Of PdfDocument) From {
PdfDocument.FromFile("document1.pdf"),
PdfDocument.FromFile("document2.pdf"),
PdfDocument.FromFile("document3.pdf")
}
Dim merged = PdfDocument.Merge(pdfDocuments)
merged.SaveAs("merged.pdf")
End Sub
End Class
iText 合并操作需要大量的样板代码:创建一个 PdfWriter 用于输出,将其包装在 PdfDocument 中,创建一个 PdfMerger,然后遍历源文件,对每个 PdfDocument 和 PdfReader 使用嵌套的 using 语句。 您还必须使用 merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages()) 指定页面范围。
IronPDF 将此过程简化为三个步骤:使用 PdfDocument.FromFile() 加载文档,使用列表调用静态 PdfDocument.Merge() 方法,然后保存。 使整个合并操作具有可读性和可维护性。 了解有关 合并和拆分 PDF 的更多信息。
示例 3:使用文本和图像创建 PDF.
之前(iText 7):
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.IO.Image;
class Program
{
static void Main()
{
string outputPath = "document.pdf";
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdf = new PdfDocument(writer))
using (Document document = new Document(pdf))
{
document.Add(new Paragraph("Sample PDF Document"));
document.Add(new Paragraph("This document contains text and an image."));
Image img = new Image(ImageDataFactory.Create("image.jpg"));
img.SetWidth(200);
document.Add(img);
}
}
}
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.IO.Image;
class Program
{
static void Main()
{
string outputPath = "document.pdf";
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdf = new PdfDocument(writer))
using (Document document = new Document(pdf))
{
document.Add(new Paragraph("Sample PDF Document"));
document.Add(new Paragraph("This document contains text and an image."));
Image img = new Image(ImageDataFactory.Create("image.jpg"));
img.SetWidth(200);
document.Add(img);
}
}
}
Imports iText.Kernel.Pdf
Imports iText.Layout
Imports iText.Layout.Element
Imports iText.IO.Image
Class Program
Shared Sub Main()
Dim outputPath As String = "document.pdf"
Using writer As New PdfWriter(outputPath),
pdf As New PdfDocument(writer),
document As New Document(pdf)
document.Add(New Paragraph("Sample PDF Document"))
document.Add(New Paragraph("This document contains text and an image."))
Dim img As New Image(ImageDataFactory.Create("image.jpg"))
img.SetWidth(200)
document.Add(img)
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = @"
<h1>Sample PDF Document</h1>
<p>This document contains text and an image.</p>
<img src='image.jpg' width='200' />";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = @"
<h1>Sample PDF Document</h1>
<p>This document contains text and an image.</p>
<img src='image.jpg' width='200' />";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html As String = "
<h1>Sample PDF Document</h1>
<p>This document contains text and an image.</p>
<img src='image.jpg' width='200' />"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("document.pdf")
End Sub
End Class
这个例子最清楚地说明了范式的转变。 iText 要求
- 三重嵌套的
using语句(PdfWriter、PdfDocument、Document) - 为每个文本元素创建
Paragraph对象,并使用new Paragraph() - 使用
ImageDataFactory.Create()加载图像 - 分别创建
Image对象并调用SetWidth() - 对每个元素调用
document.Add()
IronPDF 使用标准 HTML:标题使用 <h1>,段落使用 <p>,图像使用 <img>,并带有 width 属性。 网络开发人员可以立即利用他们现有的技能,而设计人员则可以使用他们已经掌握的 CSS 对文档进行样式设计。
关键迁移说明
范式转变:编程到 HTML 优先
这次 iText 迁移中最重要的变化是概念上的。 iText 以编程方式生成 PDF:
// iText approach
document.Add(new Paragraph("Title")
.SetTextAlignment(TextAlignment.CENTER)
.SetFontSize(24)
.SetBold());
var table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth();
table.AddHeaderCell(new Cell().Add(new Paragraph("ID")));
table.AddHeaderCell(new Cell().Add(new Paragraph("Name")));
// ... many more lines
// iText approach
document.Add(new Paragraph("Title")
.SetTextAlignment(TextAlignment.CENTER)
.SetFontSize(24)
.SetBold());
var table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth();
table.AddHeaderCell(new Cell().Add(new Paragraph("ID")));
table.AddHeaderCell(new Cell().Add(new Paragraph("Name")));
// ... many more lines
' iText approach
document.Add(New Paragraph("Title") _
.SetTextAlignment(TextAlignment.CENTER) _
.SetFontSize(24) _
.SetBold())
Dim table = New Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth()
table.AddHeaderCell(New Cell().Add(New Paragraph("ID")))
table.AddHeaderCell(New Cell().Add(New Paragraph("Name")))
' ... many more lines
IronPDF 使用 HTML 和 CSS:
//IronPDFapproach
string html = @"
<style>
h1 { text-align: center; font-size: 24px; font-weight: bold; }
table { width: 100%; border-collapse: collapse; }
th { background-color: #4CAF50; color: white; padding: 8px; }
</style>
<h1>Title</h1>
<table>
<tr><th>ID</th><th>Name</th></tr>
</table>";
var pdf = renderer.RenderHtmlAsPdf(html);
//IronPDFapproach
string html = @"
<style>
h1 { text-align: center; font-size: 24px; font-weight: bold; }
table { width: 100%; border-collapse: collapse; }
th { background-color: #4CAF50; color: white; padding: 8px; }
</style>
<h1>Title</h1>
<table>
<tr><th>ID</th><th>Name</th></tr>
</table>";
var pdf = renderer.RenderHtmlAsPdf(html);
'IronPDFapproach
Dim html As String = "
<style>
h1 { text-align: center; font-size: 24px; font-weight: bold; }
table { width: 100%; border-collapse: collapse; }
th { background-color: #4CAF50; color: white; padding: 8px; }
</style>
<h1>Title</h1>
<table>
<tr><th>ID</th><th>Name</th></tr>
</table>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
取消 AGPL 许可
iText 的 AGPL 许可证要求开源整个网络应用程序或购买昂贵的商业许可证。IronPDF的商业许可证允许在专有软件中部署,而无需病毒许可要求。
无需 pdfHTML 附加组件
iText 需要使用单独的 pdfHTML 附加组件进行 HTML 到 PDF 的转换,该组件需额外付费。IronPDF 的基础软件包中包含基于 Chromium 的完整 HTML 渲染功能。
方法替换模式
| iText 模式 | IronPDF 替代品 |
|---|---|
SetTextAlignment(TextAlignment.CENTER) |
CSS text-align: center |
SetFontSize(24) |
CSS font-size: 24px |
SetBold() |
CSS font-weight: bold |
new Table(3) |
HTML <table> |
AddHeaderCell(new Cell().Add(new Paragraph())) |
HTML <th> |
AddCell(new Cell().Add(new Paragraph())) |
HTML <td> |
故障排除
问题 1:PdfWriter/文档模式
问题:代码使用了 PdfWriter → PdfDocument → Document 嵌套模式。
解决方案:替换为 ChromePdfRenderer:
// Delete this iText pattern:
// using (var writer = new PdfWriter(outputPath))
// using (var pdfDoc = new PdfDocument(writer))
// using (var document = new Document(pdfDoc))
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
// Delete this iText pattern:
// using (var writer = new PdfWriter(outputPath))
// using (var pdfDoc = new PdfDocument(writer))
// using (var document = new Document(pdfDoc))
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(outputPath)
问题 2:HtmlConverter 未找到
问题:代码使用了 iText.Html2pdf.HtmlConverter,这需要 pdfHTML 插件。
解决方案:使用IronPDF内置的 HTML 渲染功能:
// iText (requires pdfHTML add-on)
HtmlConverter.ConvertToPdf(html, fileStream);
//IronPDF(built-in)
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
// iText (requires pdfHTML add-on)
HtmlConverter.ConvertToPdf(html, fileStream);
//IronPDF(built-in)
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
' iText (requires pdfHTML add-on)
HtmlConverter.ConvertToPdf(html, fileStream)
' IronPDF(built-in)
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(outputPath)
问题 3:PdfMerger 的复杂性
问题: iText 的 PdfMerger 需要嵌套读取器和页面范围规范。
解决方案:使用IronPDF的静态合并方法:
// iText merger pattern (delete this)
// using (PdfDocument pdfDoc = new PdfDocument(writer))
// {
// PdfMerger merger = new PdfMerger(pdfDoc);
// foreach (string file in inputFiles)
// {
// using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
// {
// merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
// }
// }
// }
//IronPDF(simple)
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
// iText merger pattern (delete this)
// using (PdfDocument pdfDoc = new PdfDocument(writer))
// {
// PdfMerger merger = new PdfMerger(pdfDoc);
// foreach (string file in inputFiles)
// {
// using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
// {
// merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
// }
// }
// }
//IronPDF(simple)
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
Imports System.Collections.Generic
' iText merger pattern (delete this)
' Using pdfDoc As New PdfDocument(writer)
' Dim merger As New PdfMerger(pdfDoc)
' For Each file As String In inputFiles
' Using sourcePdf As New PdfDocument(New PdfReader(file))
' merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages())
' End Using
' Next
' End Using
' IronPDF(simple)
Dim merged = PdfDocument.Merge(pdfDocuments)
merged.SaveAs("merged.pdf")
迁移清单
迁移前
- 清点代码库中所有 iText API 调用
- 识别程序化 PDF 构建模式(段落、表格、单元格)
- 文档 HtmlConverter 用法(pdfHTML 插件)
- 评估AGPL合规风险
- 获取IronPDF许可证密钥
代码迁移
- 删除 iText NuGet 包:
dotnet remove package itext7 - 安装 IronPdf NuGet 包:
dotnet add package IronPdf - 更新命名空间导入(
using iText.*→using IronPdf) - 将
PdfWriter/Document模式替换为ChromePdfRenderer将Paragraph/Table/Cell转换为 HTML 元素 - 将
HtmlConverter.ConvertToPdf()替换为RenderHtmlAsPdf() - 将合并操作更新至
PdfDocument.Merge() - 添加启动时许可证密钥初始化功能
测试
- 测试所有 PDF 生成路径
- 验证视觉输出是否符合预期
- 使用复杂的 HTML/CSS 内容进行测试
- 基准性能
后迁移
- 删除 iText 许可证文件和引用
- 更新文档
- 取消 iText 订阅(如适用)
- 归档旧版 iText 代码

