如何在 C# 中將 PrinceXML 遷移到 IronPDF
從 PrinceXML 遷移到 IronPDF 會將您的 PDF 產生工作流程從外部命令列進程轉變為原生 .NET 程式庫。 本指南提供了一條完整的、逐步的遷移路徑,消除了流程管理開銷,簡化了部署,並提供了除生成之外的廣泛 PDF 操作功能。
為什麼要從 PrinceXML 遷移到 IronPDF
了解 PrinceXML
PrinceXML 是一款功能強大的工具,它透過對 CSS 分頁媒體規範的專門支持,能夠出色地將 HTML 內容轉換為可完美列印的 PDF 文件。 這項專業技術使 PrinceXML 能夠以高度保真度渲染文檔,使其與預期的印刷設計保持一致——對於出版或法律文件等需要精細印刷樣式的行業來說,這是一個非常有價值的特性。
然而,PrinceXML 不是一個 .NET 函式庫,而是一個獨立的命令列工具,這可能會使那些更喜歡純 .NET 解決方案的環境的整合變得複雜。 它依賴單獨的伺服器進程,這涉及額外的系統資源管理,並可能增加專案部署的複雜性。
外部流程問題
PrinceXML 作為獨立的命令列可執行檔運行,這給 .NET 應用程式帶來了重大的架構挑戰:
1.進程管理開銷:必須產生、監控和終止外部進程。
2.不支援原生 .NET 整合:透過 stdin/stdout 或臨時檔案進行通訊。
3.部署複雜度:需要在每台伺服器上安裝 Prince。
4.按伺服器許可:每次部署都需要單獨的許可證(495 美元以上)。
5.錯誤處理難度:解析文字輸出以進行錯誤偵測。
6.無需 Async/await:無需阻塞呼叫或複雜的非同步包裝器。
7.路徑依賴:必須在 PATH 或絕對路徑中找到 Prince 執行檔。
PrinceXML 與 IronPDF 的比較
| 方面 | PrinceXML | IronPDF |
|---|---|---|
| 建築學 | 外部流程 | 原生 .NET 函式庫 |
| 一體化 | 命令列 | 直接 API |
| 部署 | 安裝在每台伺服器上 | 單一 NuGet 套件 |
| 錯誤處理 | 解析文字輸出 | .NET 異常 |
| 非同步支援 | 手動包裝機 | 原生 async/await |
| PDF 處理 | 限一代 | 完全操控(合併、分割、編輯) |
| 授權 | 每台伺服器(495美元起) | 開發商 |
| 更新 | 手動重新安裝 | NuGet 更新 |
| 偵錯 | 難的 | 完全調試器支持 |
| 數位簽名 | 不 | 是的 |
| 表格 | 不 | 是的 |
| Docker 支援 | 複雜的 | 簡單的 |
| 雲函數 | 難的 | 簡單的 |
IronPDF 憑藉其 .NET 原生功能提供了一種替代方案,它不僅限於 HTML 到 PDF 的轉換,還包括高級 PDF 操作任務,例如編輯、合併和數位簽名。 IronPDF 的 API 設計簡潔易用,讓開發人員以最少的樣板程式碼執行轉換和操作。
對於計劃在 2025 年和 2026 年採用 .NET 10 和 C# 14 的團隊而言,IronPDF 的無縫部署不需要任何外部依賴項或伺服器進程,從而減輕了整合到 .NET 框架中的負擔。
開始之前
先決條件
- .NET 環境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet 存取權限:能夠安裝 NuGet 套件
- IronPDF 許可證:請從ironpdf.com取得您的許可證密鑰。
NuGet 套件變更
# Install IronPDF
dotnet add package IronPdf
# Remove Prince wrapper if using one
dotnet remove package PrinceXMLWrapper# Install IronPDF
dotnet add package IronPdf
# Remove Prince wrapper if using one
dotnet remove package PrinceXMLWrapper許可證配置
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";搜尋 PrinceXML 用法
# Find Prince process calls
grep -r "prince" --include="*.cs" .
grep -r "Process.Start" --include="*.cs" . | grep -i prince
grep -r "@page" --include="*.css" .
grep -r "prince-" --include="*.css" .# Find Prince process calls
grep -r "prince" --include="*.cs" .
grep -r "Process.Start" --include="*.cs" . | grep -i prince
grep -r "@page" --include="*.css" .
grep -r "prince-" --include="*.css" .完整 API 參考
命名空間變更
// Before: PrinceXML
using PrinceXMLWrapper;
using System.Diagnostics;
using System.IO;
// After: IronPDF
using IronPdf;// Before: PrinceXML
using PrinceXMLWrapper;
using System.Diagnostics;
using System.IO;
// After: IronPDF
using IronPdf;命令列到方法的映射
| 王子指揮部 | IronPDF當量 |
|---|---|
prince input.html -o output.pdf | renderer.RenderHtmlFileAsPdf("input.html").SaveAs("output.pdf") |
prince --style=custom.css input.html | 在 HTML 中包含 CSS 或使用RenderingOptions |
prince --javascript | renderer.RenderingOptions.EnableJavaScript = true |
prince --no-javascript | renderer.RenderingOptions.EnableJavaScript = false |
prince --page-size=Letter | renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter |
prince --page-margin=1in | renderer.RenderingOptions.MarginTop = 72 (72 點 = 1 吋) |
prince --encrypt | pdf.SecuritySettings.OwnerPassword = "..." |
prince --user-password=pw | pdf.SecuritySettings.UserPassword = "pw" |
prince --disallow-print | pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint |
prince --disallow-copy | pdf.SecuritySettings.AllowUserCopyPasteContent = false |
prince --baseurl=http://... | renderer.RenderingOptions.BaseUrl = new Uri("http://...") |
prince --media=print | renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print |
prince --media=screen | renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Screen |
CSS @page 到 RenderingOptions 的映射
| CSS @page 屬性 | IronPDF當量 |
|---|---|
size: A4 | PaperSize = PdfPaperSize.A4 |
size: Letter | PaperSize = PdfPaperSize.Letter |
size: A4 landscape | PaperSize = PdfPaperSize.A4 + PaperOrientation = Landscape |
margin: 2cm | MarginTop/Bottom/Left/Right = 56 |
margin-top: 1in | MarginTop = 72 |
@top-center { content: "..." } | 帶有居中 div 的HtmlHeader |
@bottom-right { content: counter(page) } | 帶有{page}佔位符的HtmlFooter |
頁面尺寸轉換
| 尺寸 | 積分 | 毫米 |
|---|---|---|
| 信 | 612 x 792 | 216 x 279 |
| A4 | 595 x 842 | 210 x 297 |
| 合法的 | 612 x 1008 | 216 x 356 |
| 1吋 | 72 | 25.4 |
| 1公分 | 28.35 | 10 |
程式碼遷移範例
範例 1:HTML 檔案轉 PDF
之前(PrinceXML):
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
class Program
{
static void Main()
{
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.Convert("input.html", "output.pdf");
Console.WriteLine("PDF created successfully");
}
}// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
class Program
{
static void Main()
{
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.Convert("input.html", "output.pdf");
Console.WriteLine("PDF created successfully");
}
}(IronPDF 之後):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF created successfully");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF created successfully");
}
}這個例子展示了架構上的根本差異。 PrinceXML 需要使用可執行檔的完整路徑( "C:\\Program Files\\Prince\\engine\\bin\\prince.exe" )實例化一個Prince對象,然後使用輸入和輸出路徑呼叫Convert() 。
IronPDF 完全消除了路徑依賴性:建立一個ChromePdfRenderer ,使用 HTML 檔案路徑呼叫RenderHtmlFileAsPdf() ,然後使用SaveAs()儲存結果。 無可執行路徑,無進程管理,無路徑依賴。 請參閱HTML 轉 PDF 文件以取得完整範例。
範例 2:帶選項的 URL 轉 PDF 轉換
之前(PrinceXML):
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
class Program
{
static void Main()
{
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.SetJavaScript(true);
prince.SetEncrypt(true);
prince.SetPDFTitle("Website Export");
prince.Convert("https://example.com", "webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
class Program
{
static void Main()
{
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.SetJavaScript(true);
prince.SetEncrypt(true);
prince.SetPDFTitle("Website Export");
prince.Convert("https://example.com", "webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}(IronPDF 之後):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.PdfTitle = "Website Export";
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.Encrypt("password");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.PdfTitle = "Website Export";
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.Encrypt("password");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}此範例展示了 PrinceXML 選項如何對應到 IronPDF 屬性。 PrinceXML 在轉換之前使用 setter 方法( SetJavaScript() 、 SetEncrypt() 、 SetPDFTitle() )。 IronPDF 使用RenderingOptions屬性進行預渲染設置,並使用PdfDocument物件上的Encrypt()等後渲染方法。
關鍵映射:
prince.SetJavaScript(true)→renderer.RenderingOptions.EnableJavaScript = trueprince.SetPDFTitle("...")→renderer.RenderingOptions.PdfTitle = "..."prince.SetEncrypt(true)→pdf.Encrypt("password")(IronPDF 需要密碼)
了解更多信息,請閱讀我們的教程。
範例 3:HTML 字串到 PDF 的轉換
之前(PrinceXML):
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
using System.IO;
class Program
{
static void Main()
{
string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
File.WriteAllText("temp.html", html);
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.Convert("temp.html", "styled-output.pdf");
Console.WriteLine("Styled PDF created");
}
}// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
using System.IO;
class Program
{
static void Main()
{
string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
File.WriteAllText("temp.html", html);
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.Convert("temp.html", "styled-output.pdf");
Console.WriteLine("Styled PDF created");
}
}(IronPDF 之後):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("styled-output.pdf");
Console.WriteLine("Styled PDF created");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("styled-output.pdf");
Console.WriteLine("Styled PDF created");
}
}此範例突顯了一個關鍵區別:PrinceXML 需要檔案輸入,因此在轉換之前必須建立一個臨時檔案( File.WriteAllText("temp.html", html) )。 IronPDF 的RenderHtmlAsPdf()直接接受 HTML 字串-無需臨時文件,無需清理程式碼,也無需磁碟 I/O 開銷。
遷移 CSS 分頁媒體
雖然 PrinceXML 的 CSS 分頁媒體支援功能強大,但它會造成廠商鎖定,因為它使用 Prince 特有的 CSS,這些 CSS 在其他地方無法使用:
PrinceXML CSS:
@page {
size: A4;
margin: 2cm;
@top-center {
content: "Document Title";
}
@bottom-right {
content: counter(page);
}
}
/* Prince-specific extensions */
prince-pdf-page-label: "Chapter " counter(chapter);
prince-pdf-destination: attr(id);IronPDF C#(等效):
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 56; // ~2cm
renderer.RenderingOptions.MarginBottom = 56;
renderer.RenderingOptions.MarginLeft = 56;
renderer.RenderingOptions.MarginRight = 56;
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
MaxHeight = 40
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
MaxHeight = 25
};renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 56; // ~2cm
renderer.RenderingOptions.MarginBottom = 56;
renderer.RenderingOptions.MarginLeft = 56;
renderer.RenderingOptions.MarginRight = 56;
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
MaxHeight = 40
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
MaxHeight = 25
};常見的CSS遷移問題
問題 1:CSS @page 不起作用
IronPDF 使用 Chromium,而 Chromium 對 @page 的支援有限。 將 CSS 規則轉換為 RenderingOptions。
問題二:頁面邊距框缺失
CSS 邊距框框( @top-center 、 @bottom-right )是 Prince 特有的。 請改用HtmlHeader / HtmlFooter 。
問題 3:字串集/內容不起作用
string-set CSS 屬性是 Prince 特有的。 使用 </code> 標籤中的{html-title}佔位符<title></code> tag:</title>
<title>Chapter 1: Introduction</title><title>Chapter 1: Introduction</title>renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div>{html-title}</div>"
};renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div>{html-title}</div>"
};問題 4:計數器(頁數)錯誤
使用 IronPDF 的{total-pages}佔位符來取代 CSS 計數器。
效能比較
| 手術 | PrinceXML | IronPDF | 筆記 |
|---|---|---|---|
| 簡單的 HTML | 約400毫秒 | 約300毫秒 | IronPDF 處理中 |
| 複雜 CSS | 約600毫秒 | 約400毫秒 | 無流程開銷 |
| JavaScript 頁面 | 有限的 | 約500毫秒 | 完全支援 JS |
| 大型文檔 | 約1500毫秒 | 約1000毫秒 | 更好的記憶力 |
| 並發(10) | 約4000毫秒 | 約1500毫秒 | 執行緒池 |
| 啟動成本 | 約200毫秒 | 約50毫秒 | 沒有進程生成 |
遷移後的新功能
遷移到 IronPDF 後,您將獲得 PrinceXML 無法提供的功能:
PDF合併
var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("complete_book.pdf");var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("complete_book.pdf");水印
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");數位簽名
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);表格填寫
var pdf = PdfDocument.FromFile("form.pdf");
pdf.Form.GetFieldByName("Name").Value = "John Doe";
pdf.SaveAs("filled_form.pdf");var pdf = PdfDocument.FromFile("form.pdf");
pdf.Form.GetFieldByName("Name").Value = "John Doe";
pdf.SaveAs("filled_form.pdf");功能對比總結
| 特徵 | PrinceXML | IronPDF |
|---|---|---|
| Native .NET | 不 | 是的 |
| 外部流程 | 必需的 | 不 |
| 非同步支援 | 手工包裝 | 原生 async/await |
| CSS 分頁媒體 | 全力支持 | 透過渲染選項 |
| CSS Grid | 是的 | 是的 |
| Flexbox | 是的 | 是的 |
| JavaScript | 有限的 | 完整版 ES2024 |
| 世代 | 是的 | 是的 |
| 合併 | 不 | 是的 |
| 分裂 | 不 | 是的 |
| 編輯 | 不 | 是的 |
| 水印 | 僅限 CSS | HTML/CSS + API |
| 數位簽名 | 不 | 是的 |
| PDF/A | 是的 | 是的 |
| 加密 | 是的 | 是的 |
| 表格 | 不 | 是的 |
| NuGet 套件 | 不 | 是的 |
| 伺服器安裝 | 必需的 | 不 |
遷移清單
遷移前
- 識別所有 Prince 命令列調用
- 使用的文件 CSS @page 規則
- 列出 Prince 特有的 CSS 屬性(
prince-*,string-set) - 注意任何 Prince JavaScript 函數
- 辨識所使用的PDF功能(加密、元資料)
- 從ironpdf.com取得 IronPDF 許可證金鑰
程式碼更改
- 移除
PrinceXMLWrapperNuGet 套件 安裝IronPdfNuGet 套件 - 更新命名空間匯入
- 將
Prince實例化替換為ChromePdfRenderer - 將
prince.Convert()替換為RenderHtmlFileAsPdf()或RenderHtmlAsPdf() - 將 setter 方法轉換為
RenderingOptions屬性 - 將 @page CSS 移轉到
RenderingOptions - 將邊距框替換為
HtmlHeader/HtmlFooter - 將 CSS 計數器轉換為
{page}/{total-pages}佔位符 - 移除 HTML 字串的臨時檔案處理。
- 在應用程式啟動時新增許可證初始化
移民後
- 測試 HTML 檔案轉換
- 測試 HTML 字串轉換
- 測試 URL 轉換
- 核實頁面大小是否匹配
- 核對邊距是否匹配
- 測試頁首和頁尾
- 核對頁碼
- 測試加密/安全性
- 從伺服器移除 Prince 安裝
- 更新部署腳本






