跳過到頁腳內容
MIGRATION GUIDES

How to Migrate from Nutrient.io to IronPDF in C#

從 Nutrient.io(原 PSPDFKit)遷移到 IronPDF 可以簡化您的 .NET PDF 工作流程,因為它將使您從一個採用非同步優先模式的複雜文件智慧平台轉變為專注於 PDF 且具有簡潔同步 API 的程式庫。本指南提供了一個全面的逐步遷移路徑,該路徑消除了平台開銷,同時保留了所有必要的 PDF 功能。

為什麼要從 Nutrient.io 遷移到 IronPDF

平台複雜性問題

Nutrient.io(前身為 PSPDFKit)已從一個 PDF SDK 演變為一個全面的"文件智慧平台"。雖然這種轉變擴展了其功能,但也為那些僅需要可靠 PDF 操作的團隊帶來了重大挑戰:

1.平台過度設計:曾經的 PDF SDK 現在已經發展成為一個完整的文檔智慧平台,具有 AI 功能和文件工作流程功能,但對於簡單的 PDF 任務來說,這些功能可能並不必要。

2.企業定價: Nutrient.io 的目標客戶是大型組織,其定價不透明,需要聯絡銷售部門。 這會對中小型團隊造成障礙,並使預算規劃變得困難。

3.品牌重塑帶來的混亂: PSPDFKit → Nutrient 的轉換導致文件中同時出現兩個名稱,造成文件混亂。軟體包名稱可能仍使用 PSPDFKit,過渡期間的遷移路徑也尚不清楚。

4.非同步優先的複雜性: Nutrient.io 中的所有操作都需要 async/await 模式。 即使是簡單的操作也需要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
SHELL

許可證配置

// 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";
$vbLabelText   $csharpLabel

識別 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" .
SHELL

完整 API 參考

初始化映射

Nutrient.io (PSPDFKit) IronPDF 筆記
await PdfProcessor.CreateAsync() new ChromePdfRenderer() 無需異步
processor.Dispose() (自動或手動) 更簡單的生命週期
new PdfConfiguration { ... } renderer.RenderingOptions 基於房產

文件載入映射

Nutrient.io (PSPDFKit) IronPDF 筆記
await processor.OpenAsync(path) PdfDocument.FromFile(path) 預設同步
Document.LoadFromStream(stream) PdfDocument.FromStream(stream) 串流媒體支援
Document.LoadFromBytes(bytes) new PdfDocument(bytes) 位元組數組

PDF產生映射

Nutrient.io (PSPDFKit) IronPDF 筆記
await processor.GeneratePdfFromHtmlStringAsync(html) renderer.RenderHtmlAsPdf(html) 同步方法
await processor.GeneratePdfFromUrlAsync(url) renderer.RenderUrlAsPdf(url) 直接連結
await processor.GeneratePdfFromFileAsync(path) renderer.RenderHtmlFileAsPdf(path) HTML 文件

文檔操作映射

Nutrient.io (PSPDFKit) IronPDF 筆記
await processor.MergeAsync(docs) PdfDocument.Merge(pdfs) 同步
document.PageCount pdf.PageCount 同樣的模式
await document.SaveAsync(path) pdf.SaveAs(path) 同步
document.ToBytes() pdf.BinaryData 位元組數組

註釋和浮水印映射

Nutrient.io (PSPDFKit) IronPDF 筆記
await document.AddAnnotationAsync(index, annotation) pdf.ApplyWatermark(html) 基於HTML
new TextAnnotation("text") 浮水印中的 HTML 更靈活
annotation.Opacity = 0.5 CSS opacity: 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");
    }
}
$vbLabelText   $csharpLabel

(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");
    }
}
$vbLabelText   $csharpLabel

Nutrient.io 的方法需要幾個非同步步驟:使用await PdfProcessor.CreateAsync()建立一個PdfProcessor ,然後呼叫await processor.GeneratePdfFromHtmlStringAsync() ,最後await document.SaveAsync() 。 整個方法必須標記為async Task ,且處理器需要using語句才能正確釋放資源。

IronPDF大大簡化了這個過程。 建立一個ChromePdfRenderer ,呼叫RenderHtmlAsPdf() ,然後使用SaveAs()儲存。 無需 async/await,無需管理處理器生命週期,簡單操作無需using程式碼區塊。 對於不需要在 PDF 工作流程中使用非同步模式的開發人員來說,這種模式更加直覺。 有關其他渲染選項,請參閱HTML 轉 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");
    }
}
$vbLabelText   $csharpLabel

(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");
    }
}
$vbLabelText   $csharpLabel

Nutrient.io 的合併作業需要使用await 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");
    }
}
$vbLabelText   $csharpLabel

(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");
    }
}
$vbLabelText   $csharpLabel

這個例子突顯了建築結構上的根本差異。 Nutrient.io 使用基於註解的方法:您建立一個TextAnnotation對象,其中包含OpacityFontSize等屬性,然後遍歷每個頁面,對每個頁面呼叫await document.AddAnnotationAsync(i, watermark) 。 這需要理解註解系統並自行管理循環。

IronPDF 使用基於 HTML 的方法: ApplyWatermark()方法接受帶有 CSS 樣式的 HTML 字串。 水印會在一次呼叫中自動套用於所有頁面。 您可以透過熟悉的 CSS 屬性( coloropacityfont-size )來控制外觀,而不是透過特定於註解的物件屬性。 這種方法提供了更大的樣式彈性—您可以使用任何 HTML/CSS,包括漸層、圖像和複雜的佈局。 請參閱水印文件以取得更高級的範例。


關鍵遷移說明

異步到同步轉換

最重要的變化是移除不必要的 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");
$vbLabelText   $csharpLabel

如果您確實需要非同步操作,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 management
$vbLabelText   $csharpLabel

配置模式變更

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);
$vbLabelText   $csharpLabel

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>"
$vbLabelText   $csharpLabel

頁碼處理

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}"
};
$vbLabelText   $csharpLabel

故障排除

問題 1:未找到 PdfProcessor

問題: IronPDF 中不存在PdfProcessor類別。

解決方案:使用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();
$vbLabelText   $csharpLabel

問題 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);
$vbLabelText   $csharpLabel

問題 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>");
$vbLabelText   $csharpLabel

問題 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);
$vbLabelText   $csharpLabel

遷移清單

遷移前

  • 清點程式碼庫中所有 PSPDFKit/營養素的使用情況
  • 記錄可能需要調整的非同步模式 列出所有配置物件及其屬性
  • 辨識基於標註的特徵(浮水印、標題)
  • 審查表單處理要求
  • 取得 IronPDF 許可證密鑰

軟體包變更

  • 刪除PSPDFKit.NET NuGet 包
  • 刪除Nutrient NuGet 套件 安裝IronPdf NuGet 套件: dotnet add package IronPdf
  • 更新命名空間匯入

程式碼更改

  • 在啟動時新增許可證金鑰配置
  • PdfProcessor.CreateAsync()替換為new ChromePdfRenderer()
  • processor.GeneratePdfFromHtmlStringAsync()替換為renderer.RenderHtmlAsPdf()
  • processor.MergeAsync()替換為PdfDocument.Merge()
  • TextAnnotation浮水印轉換為 HTML 浮水印
  • 將配置物件替換為RenderingOptions屬性
  • 更新頁首/頁尾,使用有佔位符的HtmlHeaderFooter元件
  • 刪除不必要的 async/await 模式

移民後

  • 移除不再需要的 async/await
  • 執行迴歸測試,比較 PDF 輸出
  • 核對頁首/頁尾的頁碼
  • 測試浮水印渲染
  • 更新 CI/CD 管線

Curtis Chau
技術撰稿人

Curtis Chau 擁有電腦科學學士學位(卡爾頓大學),專長於前端開發,精通 Node.js、TypeScript、JavaScript 和 React。Curtis 對製作直覺且美觀的使用者介面充滿熱情,他喜歡使用現代化的架構,並製作結構良好且視覺上吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 也有濃厚的興趣,他喜歡探索整合硬體與軟體的創新方式。在空閒時間,他喜歡玩遊戲和建立 Discord bots,將他對技術的熱愛與創意結合。