如何用 C# 從 Nutrient.io 轉移到 IronPDF
從 Nutrient.io(前身為 PSPDFKit)遷移至IronPDFfor .NET 可簡化您的 .NET PDF 工作流程,從具有異步先行模式的複雜文檔智慧平台轉換為具有直接同步 API 的專注 PDF 函式庫。本指南提供全面、逐步的遷移路徑,可消除平台開銷,同時維持所有基本的 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 風格 | 同步第一 | 同步與同步選項 |
| 依賴 | 重型 | 輕量級 |
| 配置 | 複雜的組態物件 | 直接的屬性 |
| 學習曲線 | Steep (平台) | 溫和 |
| 目標使用者 | 企業 | 所有團隊規模 |
對於計劃在 2025 年和 2026 年之前採用 .NET 10 和 C# 14 的團隊而言,IronPDF 提供了一個更簡單的基礎,可以乾淨地整合,而不需要完整文件智慧平台的開銷。
開始之前
先決條件
- .NET環境: .NET Framework 4.6.2+ 或.NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet存取權限:能夠安裝NuGet套件
- IronPDF許可證:請從IronPDF取得您的許可證密鑰。
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";
' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
識別 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 |
|---|---|
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) |
文件操作映射
| 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) |
new TextAnnotation("text") |
水印中的 HTML |
annotation.Opacity = 0.5 |
CSS opacity: 0.5 |
annotation.FontSize = 48 |
CSS font-size: 48px |
程式碼遷移範例
範例 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");
}
}
Imports PSPDFKit.Pdf
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Dim htmlContent As String = "<html><body><h1>Hello World</h1></body></html>"
Using processor = Await PdfProcessor.CreateAsync()
Dim document = Await processor.GeneratePdfFromHtmlStringAsync(htmlContent)
Await document.SaveAsync("output.pdf")
End Using
End Function
End Module
After (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");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim htmlContent As String = "<html><body><h1>Hello World</h1></body></html>"
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
End Sub
End Class
Nutrient.io 的方法需要幾個非同步步驟:建立一個 PdfProcessor 和 await PdfProcessor.CreateAsync(),然後呼叫 await processor.GeneratePdfFromHtmlStringAsync(),最後呼叫 @@--CODE-18317--@@。 整個方法必須標記為 async Task,處理器需要 using 語句才能正確處置。
IronPDF 大幅簡化了這項工作。 建立 ChromePdfRenderer,呼叫 RenderHtmlAsPdf(),並使用 SaveAs() 儲存。 簡單操作無需 async/await,無需管理處理器生命週期,也無需 using 程式碼區塊。 對於 PDF 工作流程不需要 async 模式的開發人員而言,此模式較為直覺。 請參閱 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");
}
}
Imports PSPDFKit.Pdf
Imports System.Threading.Tasks
Imports System.Collections.Generic
Class Program
Shared Async Function Main() As Task
Using processor = Await PdfProcessor.CreateAsync()
Dim document1 = Await processor.OpenAsync("document1.pdf")
Dim document2 = Await processor.OpenAsync("document2.pdf")
Dim mergedDocument = Await processor.MergeAsync(New List(Of PdfDocument) From {document1, document2})
Await mergedDocument.SaveAsync("merged.pdf")
End Using
End Function
End Class
After (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");
}
}
Imports IronPdf
Imports System.Collections.Generic
Class Program
Shared Sub Main()
Dim pdf1 = PdfDocument.FromFile("document1.pdf")
Dim pdf2 = PdfDocument.FromFile("document2.pdf")
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("merged.pdf")
End Sub
End Class
Nutrient.io 合併作業需要建立一個處理器,使用 await PdfProcessor.CreateAsync(),使用單獨的 await processor.OpenAsync() 呼叫開啟每個文檔,建立一個 List<PdfDocument>,使用該清單呼叫 @@--CODE-18327--@@,最後呼叫 @@--CODE-18328--@@。 這就是基本合併的五個非同步操作。
IronPDF 將此操作簡化為四行同步程式碼:使用 PdfDocument.FromFile() 載入每個 PDF,使用靜態 PdfDocument.Merge() 方法合併,然後儲存。 無處理器生命週期、無需建立清單 (您可以直接傳遞文件)、無 async 開銷。 進一步瞭解 合併與分割 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");
}
}
Imports PSPDFKit.Pdf
Imports PSPDFKit.Pdf.Annotation
Imports System.Threading.Tasks
Class Program
Shared Async Function Main() As Task
Using processor = Await PdfProcessor.CreateAsync()
Dim document = Await processor.OpenAsync("document.pdf")
For i As Integer = 0 To document.PageCount - 1
Dim watermark = New TextAnnotation("CONFIDENTIAL") With {
.Opacity = 0.5,
.FontSize = 48
}
Await document.AddAnnotationAsync(i, watermark)
Next
Await document.SaveAsync("watermarked.pdf")
End Using
End Function
End Class
After (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");
}
}
Imports IronPdf
Imports IronPdf.Editing
Class Program
Shared Sub Main()
Dim 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")
End Sub
End Class
本範例強調一個基本的架構差異。 Nutrient.io 使用基於註解的方法:您建立一個 TextAnnotation 對象,其中包含 Opacity 和 FontSize 等屬性,然後遍歷每個頁面,對每個屬性呼叫 @@--CODE-18334--@@。 這需要瞭解註解系統並自行管理迴圈。
IronPDF 使用基於 HTML 的方法: ApplyWatermark() 方法接受具有 CSS 樣式的 HTML 字串。 水印會在一次呼叫中自動套用至所有頁面。 您可以透過熟悉的 CSS 屬性(color、opacity、font-size)來控制外觀,而不是透過特定於註解的物件屬性。 這種方法提供了更多的造型彈性-您可以使用任何 HTML/CSS,包括漸層、圖片和複雜的佈局。 請參閱水印文件以取得更高級的範例。
關鍵遷移注意事項
Async 到 Sync 的轉換
最重要的改變是移除不必要的 async/await 模式:
// Nutrient.io: Async-first
using var processor = await PdfProcessor.CreateAsync();
var document = await processor.GeneratePdfFromHtmlStringAsync(html);
await document.SaveAsync("output.pdf");
// IronPDF: Sync by default (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: Sync by default (async available when needed)
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Imports System
Imports System.Threading.Tasks
' Nutrient.io: Async-first
Using processor = Await PdfProcessor.CreateAsync()
Dim document = Await processor.GeneratePdfFromHtmlStringAsync(html)
Await document.SaveAsync("output.pdf")
End Using
' IronPDF: Sync by default (async available when needed)
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
如果您確實需要非同步操作,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
Imports IronPdf
' Nutrient.io: Processor lifecycle management
Using processor = Await PdfProcessor.CreateAsync()
' ... use processor ...
' Processor disposed at end of using block
End Using
' IronPDF: No processor lifecycle
Dim renderer As New ChromePdfRenderer()
' Reuse renderer, no complex lifecycle management
設定模式變更
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);
Imports System.Threading.Tasks
' Nutrient.io: Config object
Dim config As New PdfConfiguration With {
.PageSize = PageSize.A4,
.Margins = New Margins(20, 20, 20, 20)
}
Dim doc = Await processor.GeneratePdfFromHtmlStringAsync(html, config)
' IronPDF: Properties on RenderingOptions
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
renderer.RenderingOptions.MarginLeft = 20
renderer.RenderingOptions.MarginRight = 20
Dim pdf = renderer.RenderHtmlAsPdf(html)
註解為 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>"
' Nutrient.io: Annotation object with properties
New TextAnnotation("CONFIDENTIAL") With {.Opacity = 0.5F, .FontSize = 48}
' IronPDF: HTML with CSS
"<h1 style='opacity:0.5; font-size:48px;'>CONFIDENTIAL</h1>"
頁面編碼處理
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}"
};
' Nutrient.io: Manual loop and page counting
For i As Integer = 0 To doc.PageCount - 1
Dim footer = New TextAnnotation($"Page {i + 1} of {doc.PageCount}")
Await doc.AddAnnotationAsync(i, footer)
Next
' IronPDF: Built-in placeholders
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.HtmlFragment = "Page {page} of {total-pages}"
}
疑難排解
問題 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();
' Nutrient.io
Using processor = Await PdfProcessor.CreateAsync()
' IronPDF
Dim renderer = New ChromePdfRenderer()
問題 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);
' Nutrient.io
Dim document = Await processor.GeneratePdfFromHtmlStringAsync(html)
' IronPDF
Dim pdf = renderer.RenderHtmlAsPdf(html)
問題 3:找不到 TextAnnotation
問題: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>");
Imports System.Threading.Tasks
' Nutrient.io
Dim watermark As New TextAnnotation("DRAFT") With {.Opacity = 0.5}
Await document.AddAnnotationAsync(0, watermark)
' IronPDF
pdf.ApplyWatermark("<div style='opacity:0.5;'>DRAFT</div>")
問題 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);
Imports System.Threading.Tasks
' Nutrient.io
Dim mergedDocument = Await processor.MergeAsync(documentList)
' IronPDF
Dim merged = PdfDocument.Merge(pdf1, pdf2)
遷移清單
預遷移
- 清點程式碼庫中所有 PSPDFKit/營養素的使用情況
- 記錄可能需要調整的非同步模式 列出所有配置物件及其屬性
- 辨識基於標註的特徵(浮水印、標題)
- 審查表單處理要求
- 取得IronPDF許可證密鑰
套件變更
- 刪除
PSPDFKit.NETNuGet 套件 - 刪除
NutrientNuGet 套件 安裝IronPdfNuGet 套件: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 管線

