如何用 C# 从 Nutrient.io 迁移到 IronPDF
从 Nutrient.io 迁移到 IronPDF:完整的 C# 迁移指南。
从 Nutrient.io(原 PSPDFKit)迁移到IronPDFfor .NET,从具有异步优先模式的复杂文档智能平台迁移到具有直接同步 API 的专注 PDF 库,从而简化了您的 .NET PDF 工作流程。本指南提供了一个全面、逐步的迁移路径,可消除平台开销,同时保持所有基本的 PDF 功能。
为什么要从 Nutrient.io 迁移到 IronPDF.
平台复杂性问题
Nutrient.io(前身为 PSPDFKit)已从 PDF SDK 发展成为一个全面的 "文档智能平台"。这种转变在拓宽功能的同时,也给只需要可靠 PDF 操作的团队带来了巨大的挑战:
1.平台过度工程:曾经的 PDF SDK 现在已成为一个完整的文档智能平台,具有人工智能功能和文档工作流程功能,而这些功能对于简单的 PDF 任务来说可能是不必要的。
2.企业定价:Nutrient.io 定位于大型企业,其定价不透明,需要联系销售人员。 这给中小型团队造成了障碍,也使预算规划变得困难。
3.品牌重塑:PSPDFKit → Nutrient 的过渡产生了文档问题,因为这两个名称都存在引用。软件包名称可能仍使用 PSPDFKit,过渡期间的迁移路径仍不明确。
4.异步优先复杂性:Nutrient.io 中的一切都需要异步/等待模式。 即使是简单的操作也需要PdfProcessor.CreateAsync()进行初始化,基本任务需要使用异步方法,从而增加了同步工作流的开销。
5.重度依赖性:完整平台需要更多资源,占用更多软件包空间、更多初始化时间和额外配置。
Nutrient.io 与IronPDF对比
| 方面 | Nutrient.io (PSPDFKit) | IronPDF |
|---|---|---|
| 翻译重点 | 文档智能平台 | PDF 库 |
| 定价 | 企业(联系销售) | 透明、公开 |
| 结构 | 复杂的平台 | 简单库 |
| API 风格 | 异步优先 | 同步与异步选项 |
| 依赖关系 | 重型 | 轻量级 |
| 配置 | 复杂的配置对象 | 简单明了的属性 |
| 学习曲线 | 陡峭(平台) | 温和(库) |
| 目标用户 | 企业 | 所有团队规模 |
对于计划在 2025 年和 2026 年之前采用 .NET 10 和 C# 14 的团队来说,IronPDF 提供了一个更简单的基础,可以干净利落地集成,而不需要完整文档智能平台的开销。
开始之前
前提条件
1..NET环境:.NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+ 2.NuGet 访问:安装 NuGet 软件包的能力 3.IronPDF 许可证:从 ironpdf.com 获取许可证密钥
NuGet 软件包变更
# Remove Nutrient/PSPDFKit packages
dotnet remove package PSPDFKit.NET
dotnet remove package PSPDFKit.PDF
dotnet remove package Nutrient
dotnet remove package Nutrient.PDF
# Install IronPDF
dotnet add package IronPdf# Remove Nutrient/PSPDFKit packages
dotnet remove package PSPDFKit.NET
dotnet remove package PSPDFKit.PDF
dotnet remove package Nutrient
dotnet remove package Nutrient.PDF
# 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";IRON VB CONVERTER ERROR developers@ironsoftware.com识别 Nutrient.io 的用法
# Find all Nutrient/PSPDFKit references
grep -r "PSPDFKit\|Nutrient\|PdfProcessor\|PdfConfiguration" --include="*.cs" .# Find all Nutrient/PSPDFKit references
grep -r "PSPDFKit\|Nutrient\|PdfProcessor\|PdfConfiguration" --include="*.cs" .完整的 API 参考
初始化映射
| Nutrient.io (PSPDFKit) | IronPDF | 备注 |
|---|---|---|
| <代码>等待 PdfProcessor.CreateAsync()</ 代码 | <代码>new ChromePdfRenderer()</ 代码 | 无需异步 |
| <代码>processor.Dispose()</代码 | (自动或手动) | 更简单的生命周期 |
new PdfConfiguration { ... } | <代码>renderer.RenderingOptions</代码 | 基于属性 |
文档加载映射
| Nutrient.io (PSPDFKit) | IronPDF | 备注 |
|---|---|---|
| <代码>等待处理器.OpenAsync(路径)</代码 | <代码>PdfDocument.FromFile(路径)</代码 | 默认同步 |
| <代码>Document.LoadFromStream(stream)</代码 | <代码>PdfDocument.FromStream(流)</代码 | 流支持 |
| <代码>Document.LoadFromBytes(字节)</代码 | <代码>new PdfDocument(字节)</代码 | 字节数组 |
PDF 生成映射
| Nutrient.io (PSPDFKit) | IronPDF | 备注 |
|---|---|---|
| <代码>等待处理器.GeneratePdfFromHtmlStringAsync(html)</代码 | <代码>renderer.RenderHtmlAsPdf(html)</代码 | 同步方法 |
await processor.GeneratePdfFromUrlAsync(url)<br | <代码>renderer.RenderUrlAsPdf(url)</代码 | 直接 URL |
| <代码>await processor.GeneratePdfFromFileAsync(path)</ 代码 | <代码>renderer.RenderHtmlFileAsPdf(path)</代码 | HTML 文件 |
文档操作映射
| Nutrient.io (PSPDFKit) | IronPDF | 备注 |
|---|---|---|
| <代码>等待处理器.MergeAsync(docs)</代码 | <代码>PdfDocument.Merge(pdfs)</代码 | 同步 |
| <代码>document.PageCount</代码 | <代码>pdf.PageCount</代码 | 相同模式 |
| <代码>等待 document.SaveAsync(path)</ 代码 | <代码>pdf.SaveAs(路径)</代码 | 同步 |
| <代码>document.ToBytes()</代码 | <代码>pdf.BinaryData</代码 | 字节数组 |
注释和水印映射
| Nutrient.io (PSPDFKit) | IronPDF | 备注 |
|---|---|---|
| <代码>等待 document.AddAnnotationAsync(index, annotation)</ 代码 | <代码>pdf.ApplyWatermark(html)</代码 | 基于 HTML |
| <代码>new TextAnnotation("text")</ 代码 | 水印中的 HTML | 更灵活 |
| <代码>annotation.Opacity = 0.5</代码 | CSS <代码>不透明度:0.5</代码 | CSS 定型 |
| <代码>annotation.FontSize = 48</ 代码 | CSS font-size: 48px | CSS 定型 |
代码迁移示例
示例 1:HTML 到 PDF 的转换
之前(Nutrient.io):
// NuGet: Install-Package PSPDFKit.Dotnet
using PSPDFKit.Pdf;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var htmlContent = "<html><body><h1>Hello World</h1></body></html>";
using var processor = await PdfProcessor.CreateAsync();
var document = await processor.GeneratePdfFromHtmlStringAsync(htmlContent);
await document.SaveAsync("output.pdf");
}
}// NuGet: Install-Package PSPDFKit.Dotnet
using PSPDFKit.Pdf;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var htmlContent = "<html><body><h1>Hello World</h1></body></html>";
using var processor = await PdfProcessor.CreateAsync();
var document = await processor.GeneratePdfFromHtmlStringAsync(htmlContent);
await document.SaveAsync("output.pdf");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comAfter (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var htmlContent = "<html><body><h1>Hello World</h1></body></html>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var htmlContent = "<html><body><h1>Hello World</h1></body></html>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comNutrient.io 方法需要几个异步步骤:使用<代码>等待 PdfProcessor.CreateAsync()</ 代码创建 PdfProcessor ,然后调用 await processor.GeneratePdfFromHtmlStringAsync() ,最后调用 await document.SaveAsync() 。 整个方法必须标记为async Task,处理器需要使用using语句进行正确处理。
IronPdf 大幅简化了这一工作。 创建ChromePdfRenderer,调用RenderHtmlAsPdf(),并使用SaveAs()保存。 不需要 async/await,不需要管理处理器生命周期,也不需要 using 块来进行简单操作。 对于在 PDF 工作流程中不需要异步模式的开发人员来说,这种模式更为直观。 有关其他渲染选项,请参阅 HTML to PDF 文档。
示例 2:合并多个 PDF 文件
之前(Nutrient.io):
// NuGet: Install-Package PSPDFKit.Dotnet
using PSPDFKit.Pdf;
using System.Threading.Tasks;
using System.Collections.Generic;
class Program
{
static async Task Main()
{
using var processor = await PdfProcessor.CreateAsync();
var document1 = await processor.OpenAsync("document1.pdf");
var document2 = await processor.OpenAsync("document2.pdf");
var mergedDocument = await processor.MergeAsync(new List<PdfDocument> { document1, document2 });
await mergedDocument.SaveAsync("merged.pdf");
}
}// NuGet: Install-Package PSPDFKit.Dotnet
using PSPDFKit.Pdf;
using System.Threading.Tasks;
using System.Collections.Generic;
class Program
{
static async Task Main()
{
using var processor = await PdfProcessor.CreateAsync();
var document1 = await processor.OpenAsync("document1.pdf");
var document2 = await processor.OpenAsync("document2.pdf");
var mergedDocument = await processor.MergeAsync(new List<PdfDocument> { document1, document2 });
await mergedDocument.SaveAsync("merged.pdf");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comAfter (IronPDF):
// 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(pdf1, pdf2);
merged.SaveAs("merged.pdf");
}
}// 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(pdf1, pdf2);
merged.SaveAs("merged.pdf");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comNutrient.io 的合并操作需要使用<代码>等待 PdfProcessor.CreateAsync()</ 代码创建一个处理器,使用单独的 await processor.OpenAsync() 调用打开每个文档,创建一个 List<PdfDocument> ,使用该列表调用 await processor.MergeAsync() ,最后调用 await mergedDocument.SaveAsync() 。 这就是基本合并的五个异步操作。
IronPDF 将此简化为四行同步操作:使用 PdfDocument.FromFile() 加载每个 PDF,使用静态 PdfDocument.Merge() 方法合并,然后保存。 无处理器生命周期,无需创建列表(可直接传递文档),无异步开销。 了解有关 合并和拆分 PDF 的更多信息。
示例 3:添加水印
之前(Nutrient.io):
// NuGet: Install-Package PSPDFKit.Dotnet
using PSPDFKit.Pdf;
using PSPDFKit.Pdf.Annotation;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var processor = await PdfProcessor.CreateAsync();
var document = await processor.OpenAsync("document.pdf");
for (int i = 0; i < document.PageCount; i++)
{
var watermark = new TextAnnotation("CONFIDENTIAL")
{
Opacity = 0.5,
FontSize = 48
};
await document.AddAnnotationAsync(i, watermark);
}
await document.SaveAsync("watermarked.pdf");
}
}// NuGet: Install-Package PSPDFKit.Dotnet
using PSPDFKit.Pdf;
using PSPDFKit.Pdf.Annotation;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var processor = await PdfProcessor.CreateAsync();
var document = await processor.OpenAsync("document.pdf");
for (int i = 0; i < document.PageCount; i++)
{
var watermark = new TextAnnotation("CONFIDENTIAL")
{
Opacity = 0.5,
FontSize = 48
};
await document.AddAnnotationAsync(i, watermark);
}
await document.SaveAsync("watermarked.pdf");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comAfter (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Editing;
class Program
{
static void Main()
{
var pdf = PdfDocument.FromFile("document.pdf");
pdf.ApplyWatermark("<h1 style='color:gray;opacity:0.5;'>CONFIDENTIAL</h1>",
50,
VerticalAlignment.Middle,
HorizontalAlignment.Center);
pdf.SaveAs("watermarked.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Editing;
class Program
{
static void Main()
{
var pdf = PdfDocument.FromFile("document.pdf");
pdf.ApplyWatermark("<h1 style='color:gray;opacity:0.5;'>CONFIDENTIAL</h1>",
50,
VerticalAlignment.Middle,
HorizontalAlignment.Center);
pdf.SaveAs("watermarked.pdf");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.com这个例子突出了一个基本的架构差异。 Nutrient.io 使用一种基于注释的方法:您可以创建一个TextAnnotation对象,该对象具有Opacity和FontSize等属性,然后在每个页面中循环调用await document.AddAnnotationAsync(i, watermark) 。 这就需要了解注释系统并自己管理循环。
IronPdf 采用基于 HTML 的方法:ApplyWatermark()方法接受带有 CSS 样式的 HTML 字符串。 水印会在一次调用中自动应用到所有页面。 您可以通过熟悉的 CSS 属性(color、opacity、font-size)而不是特定于注解的对象属性来控制外观。 这种方法提供了更大的样式灵活性--您可以使用任何 HTML/CSS,包括渐变、图像和复杂布局。 有关高级示例,请参见 watermark 文档。
关键迁移说明
同步到同步转换
最大的改动是删除了不必要的 async/await 模式:
// Nutrient.io: Async-first
using var processor = await PdfProcessor.CreateAsync();
var document = await processor.GeneratePdfFromHtmlStringAsync(html);
await document.SaveAsync("output.pdf");
// IronPDF:默认同步(async available when needed)
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");// Nutrient.io: Async-first
using var processor = await PdfProcessor.CreateAsync();
var document = await processor.GeneratePdfFromHtmlStringAsync(html);
await document.SaveAsync("output.pdf");
// IronPDF:默认同步(async available when needed)
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");IRON VB CONVERTER ERROR developers@ironsoftware.com如果您确实需要异步操作,IronPDF 提供了异步变体,如 RenderHtmlAsPdfAsync() 。
消除处理器生命周期
Nutrient.io 需要创建和处理处理器:
// Nutrient.io: Processor lifecycle management
using var processor = await PdfProcessor.CreateAsync();
// ... use processor ...
// Processor disposed at end of using block
// IronPDF: No processor lifecycle
var renderer = new ChromePdfRenderer();
// Reuse renderer, no complex lifecycle management// Nutrient.io: Processor lifecycle management
using var processor = await PdfProcessor.CreateAsync();
// ... use processor ...
// Processor disposed at end of using block
// IronPDF: No processor lifecycle
var renderer = new ChromePdfRenderer();
// Reuse renderer, no complex lifecycle managementIRON VB CONVERTER ERROR developers@ironsoftware.com配置模式更改
Nutrient.io 使用配置对象; IronPdf 使用属性:
// Nutrient.io: Config object
var config = new PdfConfiguration
{
PageSize = PageSize.A4,
Margins = new Margins(20, 20, 20, 20)
};
var doc = await processor.GeneratePdfFromHtmlStringAsync(html, config);
// IronPDF: Properties on RenderingOptions
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
var pdf = renderer.RenderHtmlAsPdf(html);// Nutrient.io: Config object
var config = new PdfConfiguration
{
PageSize = PageSize.A4,
Margins = new Margins(20, 20, 20, 20)
};
var doc = await processor.GeneratePdfFromHtmlStringAsync(html, config);
// IronPDF: Properties on RenderingOptions
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;
var pdf = renderer.RenderHtmlAsPdf(html);IRON VB CONVERTER ERROR developers@ironsoftware.com注释到 HTML 水印
用 HTML 字符串替换注释对象:
// Nutrient.io: Annotation object with properties
new TextAnnotation("CONFIDENTIAL") { Opacity = 0.5f, FontSize = 48 }
// IronPDF: HTML with CSS
"<h1 style='opacity:0.5; font-size:48px;'>CONFIDENTIAL</h1>"// Nutrient.io: Annotation object with properties
new TextAnnotation("CONFIDENTIAL") { Opacity = 0.5f, FontSize = 48 }
// IronPDF: HTML with CSS
"<h1 style='opacity:0.5; font-size:48px;'>CONFIDENTIAL</h1>"IRON VB CONVERTER ERROR developers@ironsoftware.com页码处理
Nutrient.io 需要手动计算页数; IronPdf 已内置占位符:
// Nutrient.io: Manual loop and page counting
for (int i = 0; i < doc.PageCount; i++)
{
var footer = new TextAnnotation($"Page {i + 1} of {doc.PageCount}");
await doc.AddAnnotationAsync(i, footer);
}
// IronPDF: Built-in placeholders
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "Page {page} of {total-pages}"
};// Nutrient.io: Manual loop and page counting
for (int i = 0; i < doc.PageCount; i++)
{
var footer = new TextAnnotation($"Page {i + 1} of {doc.PageCount}");
await doc.AddAnnotationAsync(i, footer);
}
// IronPDF: Built-in placeholders
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "Page {page} of {total-pages}"
};IRON VB CONVERTER ERROR developers@ironsoftware.com故障排除
问题 1:未找到 PdfProcessor
问题:PdfProcessor 类在IronPDF中不存在。
解决方案:使用 ChromePdfRenderer:
// Nutrient.io
using var processor = await PdfProcessor.CreateAsync();
// IronPDF
var renderer = new ChromePdfRenderer();// Nutrient.io
using var processor = await PdfProcessor.CreateAsync();
// IronPDF
var renderer = new ChromePdfRenderer();IRON VB CONVERTER ERROR developers@ironsoftware.com问题 2:GeneratePdfFromHtmlStringAsync 未找到
问题:不存在异步 HTML 方法。
解决方案:使用 RenderHtmlAsPdf():
// Nutrient.io
var document = await processor.GeneratePdfFromHtmlStringAsync(html);
// IronPDF
var pdf = renderer.RenderHtmlAsPdf(html);// Nutrient.io
var document = await processor.GeneratePdfFromHtmlStringAsync(html);
// IronPDF
var pdf = renderer.RenderHtmlAsPdf(html);IRON VB CONVERTER ERROR developers@ironsoftware.com问题 3:未找到文本注释
问题:IronPDF 中不存在注释类。
解决方案:使用基于 HTML 的水印:
// Nutrient.io
var watermark = new TextAnnotation("DRAFT") { Opacity = 0.5 };
await document.AddAnnotationAsync(0, watermark);
// IronPDF
pdf.ApplyWatermark("<div style='opacity:0.5;'>DRAFT</div>");// Nutrient.io
var watermark = new TextAnnotation("DRAFT") { Opacity = 0.5 };
await document.AddAnnotationAsync(0, watermark);
// IronPDF
pdf.ApplyWatermark("<div style='opacity:0.5;'>DRAFT</div>");IRON VB CONVERTER ERROR developers@ironsoftware.com问题 4:未找到 MergeAsync
问题:不存在异步合并方法。
解决方案:使用静态 PdfDocument.Merge():
// Nutrient.io
var mergedDocument = await processor.MergeAsync(documentList);
// IronPDF
var merged = PdfDocument.Merge(pdf1, pdf2);// Nutrient.io
var mergedDocument = await processor.MergeAsync(documentList);
// IronPDF
var merged = PdfDocument.Merge(pdf1, pdf2);IRON VB CONVERTER ERROR developers@ironsoftware.com迁移清单
迁移前
- [ ] 清点代码库中所有 PSPDFKit/营养素的使用情况
- [ ] 记录可能需要调整的异步模式
- [ ] 列出所有配置对象及其属性
- [ ] 识别基于注释的特征(水印、页眉)
- [ ] 审查表单处理要求
- [ ] 获取 IronPdf 许可证密钥
软件包变更
- [ ] 删除
PSPDFKit.NETNuGet 软件包 - [ ] 删除
NutrientNuGet 软件包 - [ ] 安装
IronPDFNuGet 软件包:<代码>dotnet 添加软件包 IronPdf - [更新命名空间导入
代码更改
- [ ] 在启动时添加许可证密钥配置
- [ ] 将
PdfProcessor.CreateAsync()替换为<代码>new ChromePdfRenderer()</ 代码。 - [ ] 将
processor.GeneratePdfFromHtmlStringAsync()替换为renderer.RenderHtmlAsPdf()。 - [ ] 将
processor.MergeAsync()替换为PdfDocument.Merge()。 - [ ] 将
TextAnnotation水印转换为 HTML 水印 - [用
RenderingOptions属性替换配置对象 - [ ] 更新页眉/页脚以使用
HtmlHeaderFooter和占位符 - [ ] 删除不必要的 async/await 模式
后迁移
- [ ] 删除不再需要的 async/await
- [运行比较 PDF 输出的回归测试
- [ ] 用页码验证页眉/页脚
- [ ] 测试水印渲染
- [更新 CI/CD 管道
结论
从 Nutrient.io 迁移到 IronPDF,用专注的 PDF 库取代复杂的文档智能平台,从而简化您的 PDF 工作流程。 迁移消除了异步优先的复杂性、处理器生命周期管理和基于注释的方法,转而采用直接的同步 API 和基于 HTML 的样式。
本次迁移的主要变化有 1.架构:文档智能平台 → 聚焦 PDF 库 2.API 风格:异步优先 → 带有异步选项的同步 3.初始化:await PdfProcessor.CreateAsync() → new ChromePdfRenderer(). 4.HTML 转 PDF:<代码>GeneratePdfFromHtmlStringAsync()</代码> → <代码>RenderHtmlAsPdf()</代码 5.合并:<代码>processor.MergeAsync(list)</代码> → <代码>PdfDocument.Merge(pdf1, pdf2)</ 代码 6.水印:TextAnnotation 对象 → 使用 CSS 的 HTML 字符串 7.页码:手动循环 → {page}和 {total-pages}占位符






