如何將 HTML 字串渲染為 C# PDF
從PrinceXML遷移到IronPDF將您的PDF生成工作流從外部命令行過程轉變為原生.NET程式庫。 本指南提供完整的逐步遷移路徑,消除了過程管理的負擔,簡化了部署,並提供了超越生成的廣泛PDF操作能力。
為什麼要從PrinceXML遷移到IronPDF
了解PrinceXML
PrinceXML是一個先進的工具,專為將HTML內容轉換為完美印刷的PDF文件而設計,通過其對CSS頁面媒體規範的專門支持。 這種專業化使PrinceXML能夠與預期的印刷設計高保真度地渲染文件,這對於需要詳細印刷樣式的行業來說是一個有價值的特性,比如出版或法律文件。
然而,PrinceXML不是一個.NET程式庫,它作為一個單獨的命令行工具運行,這可能會對偏好純.NET解決方案的環境造成整合上的困難。 它依賴於一個單獨的伺服器過程,涉及額外的系統資源管理,並可能增加專案部署的複雜性。
外部過程問題
PrinceXML作為一個單獨的命令行可執行文件運行,對.NET應用程式構架構成了顯著的挑戰:
-
過程管理負擔: 必須生成、監控和終止外部過程。
-
沒有原生.NET整合: 通過stdin/stdout或臨時文件進行通信。
-
部署複雜性: 需要在每台伺服器上安裝Prince。
-
每伺服器授權: 每次部署需要單獨的授權。
-
錯誤處理困難: 解析文字輸出以檢測錯誤。
-
沒有異步/等待: 需要阻塞呼叫或複雜的異步包裝器。
- 路徑依賴性: 必須在PATH或絕對路徑中找到Prince可執行文件。
PrinceXML與IronPDF比較
| 方面 | PrinceXML | IronPDF |
|---|---|---|
| 架構 | 外部過程 | 原生.NET程式庫 |
| 整合 | 命令行 | 直接API |
| 部署 | 安裝在每台伺服器上 | 單個NuGet套件 |
| 錯誤處理 | 解析文字輸出 | .NET異常 |
| 異步支援 | 手動包裝器 | 原生async/await |
| PDF 操作 | 僅限生成 | 全面操作(合併、拆分、編輯) |
| 授權 | 桌面 $495 / 伺服器 $3,800; free non-commercial use with logo watermark | 每位開發者 |
| 更新 | 手動重新安裝 | NuGet更新 |
| 除錯 | 困難 | 完整除錯器支持 |
| 數位簽名 | 否 | 是 |
| 表單 | 否 | 是 |
| Docker支持 | 複雜 | 簡單 |
| 雲功能 | 困難 | 容易 |
IronPDF提供了一種替代方案,它具備.NET原生功能,不僅僅是HTML到PDF轉換,而且包括如編輯、合併和數位簽名等進階PDF操作任務。 IronPDF的API設計簡單易用,讓開發者能夠以最少的樣板程式碼進行轉換和操作。
對於採用現代.NET的團隊,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";
' 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 PrinceXML.Wrapper;
using System.Diagnostics;
using System.IO;
// After: IronPDF
using IronPdf;
// Before: PrinceXML
using PrinceXML.Wrapper;
using System.Diagnostics;
using System.IO;
// After: IronPDF
using IronPdf;
Imports IronPdf
Imports System.Diagnostics
Imports System.IO
命令行到方法映射
| Prince Command | 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) } |
使用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 PrinceXML.Wrapper;
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 PrinceXML.Wrapper;
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");
}
}
Imports PrinceXML.Wrapper
Imports System
Class Program
Shared Sub Main()
Dim prince As New Prince("C:\Program Files\Prince\engine\bin\prince.exe")
prince.Convert("input.html", "output.pdf")
Console.WriteLine("PDF created successfully")
End Sub
End Class
之後(IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
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()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF created successfully");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF created successfully")
End Sub
End Class
此範例說明基本的架構差異。 PrinceXML需要實例化一個Convert()。
IronPDF完全消除了路徑依賴性:建立一個SaveAs()寫入結果。 沒有可執行文件路徑,沒有過程管理,沒有路徑依賴性。 查看更多HTML到PDF文件以獲得完整的範例。
範例2: 有選項的URL轉換為PDF
之前(PrinceXML):
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXML.Wrapper;
using System;
class Program
{
static void Main()
{
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.JavaScript = true;
prince.Encrypt = true;
prince.PdfTitle = "Website Export";
prince.Convert("https://example.com", "webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXML.Wrapper;
using System;
class Program
{
static void Main()
{
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
prince.JavaScript = true;
prince.Encrypt = true;
prince.PdfTitle = "Website Export";
prince.Convert("https://example.com", "webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}
Imports PrinceXML.Wrapper
Imports System
Class Program
Shared Sub Main()
Dim prince As New Prince("C:\Program Files\Prince\engine\bin\prince.exe")
prince.JavaScript = True
prince.Encrypt = True
prince.PdfTitle = "Website Export"
prince.Convert("https://example.com", "webpage.pdf")
Console.WriteLine("URL converted to PDF")
End Sub
End Class
之後(IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.Title = "Website Export";
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SecuritySettings.OwnerPassword = "owner-password";
pdf.SecuritySettings.UserPassword = "user-password";
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.Title = "Website Export";
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SecuritySettings.OwnerPassword = "owner-password";
pdf.SecuritySettings.UserPassword = "user-password";
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = True
renderer.RenderingOptions.Title = "Website Export"
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SecuritySettings.OwnerPassword = "owner-password"
pdf.SecuritySettings.UserPassword = "user-password"
pdf.SaveAs("webpage.pdf")
Console.WriteLine("URL converted to PDF")
End Sub
End Class
此範例顯示了PrinceXML選項如何映射到IronPDF屬性。 PrinceXML在轉換之前,將配置暴露為PdfTitle)上的屬性。 IronPDF使用PdfDocument上後應用加密。
關鍵映射:
prince.JavaScript = true→renderer.RenderingOptions.EnableJavaScript = trueprince.PdfTitle = "..."→renderer.RenderingOptions.Title = "..."prince.Encrypt = true→pdf.SecuritySettings.OwnerPassword = "..."/pdf.SecuritySettings.UserPassword = "..."
在我們的教程中了解更多。
範例3: HTML字串到PDF轉換
之前(PrinceXML):
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXML.Wrapper;
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>";
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
// ConvertString accepts a raw HTML/XML string directly
prince.ConvertString(html, "styled-output.pdf");
Console.WriteLine("Styled PDF created");
}
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXML.Wrapper;
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>";
Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
// ConvertString accepts a raw HTML/XML string directly
prince.ConvertString(html, "styled-output.pdf");
Console.WriteLine("Styled PDF created");
}
}
Imports PrinceXML.Wrapper
Imports System
Module Program
Sub Main()
Dim html As String = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>"
Dim prince As New Prince("C:\Program Files\Prince\engine\bin\prince.exe")
' ConvertString accepts a raw HTML/XML string directly
prince.ConvertString(html, "styled-output.pdf")
Console.WriteLine("Styled PDF created")
End Sub
End Module
之後(IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
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()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
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");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim html As String = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>"
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("styled-output.pdf")
Console.WriteLine("Styled PDF created")
End Sub
End Class
兩個程式庫都可以直接接受HTML字串:PrinceXML通過RenderHtmlAsPdf()。 架構上的差異依然存在——PrinceXML的prince二進製程式傳遞輸入,而IronPDF則在內部進行渲染,無需外部可執行文件。
遷移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
};
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 With {
.HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
.MaxHeight = 40
}
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
.MaxHeight = 25
}
常見CSS遷移問題
問題1: CSS @page無法正常工作
IronPDF使用Chromium,而Chromium對@page的支持有限。 將CSS規則轉換為RenderingOptions。
問題2: 缺少頁面邊距框
CSS邊距框(@bottom-right)是Prince專用的。 使用HtmlFooter代替。
問題3: string-set/content無法正常工作
string-set CSS屬性是Prince專用的。 從{html-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: counter(pages)不正確
使用IronPDF的{total-pages}佔位符代替CSS計數器。
性能比較
| 操作 | PrinceXML | IronPDF |
|---|---|---|
| 簡單的HTML | ~400毫秒 | ~300毫秒 |
| 複雜CSS | ~600毫秒 | ~400毫秒 |
| JavaScript頁面 | 有限 | ~500毫秒 |
| 大型文件 | ~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");
Dim pdf1 = PdfDocument.FromFile("chapter1.pdf")
Dim pdf2 = PdfDocument.FromFile("chapter2.pdf")
Dim 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>");
IRON VB CONVERTER ERROR developers@ironsoftware.com
數位簽名
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
Dim 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");
Dim pdf = PdfDocument.FromFile("form.pdf")
pdf.Form.GetFieldByName("Name").Value = "John Doe"
pdf.SaveAs("filled_form.pdf")
功能比較總結
| 功能 | PrinceXML | IronPDF |
|---|---|---|
| 原生.NET | 否 | 是 |
| 外部過程 | 必需的 | 否 |
| 異步支援 | 手動包裝 | 原生async/await |
| CSS Paged Media | 支援 | 通過RenderingOptions |
| CSS網格 | 是 | 是 |
| Flexbox | 是 | 是 |
| JavaScript | 有限 | 完整的ES2024 |
| 生成 | 是 | 是 |
| 合併 | 否 | 是 |
| 分割 | 否 | 是 |
| 編輯 | 否 | 是 |
| 浮水印 | 僅CSS | HTML/CSS + API |
| 數位簽名 | 否 | 是 |
| PDF/A | 是 | 是 |
| 加密 | 是 | 是 |
| 表單 | 否 | 是 |
| NuGet 套件 | 否 | 是 |
| 伺服器安裝 | 必需的 | 否 |
遷移檢查表
遷移前
- 確認所有Prince命令行調用
- 記錄使用的CSS @page規則
- 列出Prince專用CSS屬性(
string-set) - 記錄任何Prince JavaScript函式
- 確認使用的PDF功能(加密,元資料)
- 獲取IronPDF授權金鑰來自ironpdf.com
程式碼變更
- 移除
PrinceXMLWrapperNuGet套件 - 安裝
IronPdfNuGet套件 - 更新命名空間導入
- 用
Prince實例化 - 用
prince.Convert() - 將設置方法轉換為
RenderingOptions屬性 - 遷移@page CSS到
RenderingOptions - 用
HtmlFooter替換邊距框 - 將CSS計數器轉換為
{total-pages}佔位符 - 刪除HTML字串的臨時文件處理
- 在應用程式啟動時新增授權初始化
遷移後
- 測試HTML文件轉換
- 測試HTML字串轉換
- 測試URL轉換
- 驗證頁面尺寸匹配
- 驗證邊距匹配
- 測試標頭和頁尾
- 驗證頁碼
- 測試加密/安全性
- 從伺服器移除Prince安裝
- 更新部署腳本

