FO.NET vs IronPDF for .NET:技術比較指南
當 .NET 開發人員尋找 PDF 產生解決方案時,FO.NET 脫穎而出,成為將 XSL-FO 文件轉換為 PDF 的專用工具。 然而,由於它依賴過時的 XSL-FO 語言、缺乏 HTML/CSS 支援以及已停止維護,許多團隊開始考慮替代方案。IronPDF提供了一個使用大多數開發人員已經熟悉的 HTML/CSS 網路標準的現代化解決方案,它採用 Chromium 渲染引擎,並定期每月更新。
本次比較從相關技術方面對這兩個庫進行了審查,以幫助專業開發人員和架構師根據其 .NET PDF 需求做出明智的決策。
瞭解 FO.NET
FO.NET(也稱為 FoNet)是一個開放源碼函式庫,設計用來使用 C# 將 XSL Formatting Object (XSL-FO) 文件轉換成 PDF。 本函式庫採用 Apache 2.0 許可證,並將 XSL-FO 語言直接對應到 PDF 格式。
FO.NET 使用 FonetDriver 作為其主要類別,藉由 Make() 工廠方法建立驅動程式實體,以及 Render() 方法處理 XSL-FO 輸入串流以產生 PDF 輸出串流。 配置發生在 XSL-FO 標記本身,使用的元素包括 fo:simple-page-master、fo:layout-master-set,以及頁邊空白、頁面大小和字型的格式屬性。
一個顯著的限制在於,FO.NET 需要 XSL-FO 知識——XSL-FO 是基於 XML 的語言,是 W3C 於 2001 年制定的規範,自 2006 年以來未進行更新。該庫不支援 HTML 或 CSS,也不能直接渲染網頁。 在當今的技術領域,XSL-FO 已被普遍認為過時,只有不到 1% 的開發人員精通它,而超過 98% 的開發人員了解 HTML/CSS。
CodePlex 原始資源庫已停用,GitHub 分叉也不再積極維護。 FO.NET 內部依賴 System.Drawing,因此無法在 Linux/macOS 上運作,只能在 Windows 上部署。
了解 IronPDF
IronPDF 是一個 .NET PDF 函式庫,它使用 HTML/CSS 進行文件樣式和佈局,採用開發中常用的 Web 標準。 該函式庫使用 Chromium 渲染引擎,提供完整的 CSS3 支援,包括 Flexbox 和 Grid 佈局,以及JavaScript執行。
IronPDF 使用 ChromePdfRenderer 作為其主要的渲染類別,而 RenderingOptions 則為頁面大小、邊界、頁首、頁尾以及其他 PDF 設定提供程式化的設定。 該函式庫支援直接 URL 呈現、HTML 字串呈現和 HTML 檔案呈現,產生 PdfDocument 物件,這些物件可以儲存、合併、保全或進一步處理。
IronPDF 持續維護,每月發布新版本,支援真正的跨平台部署(Windows、Linux、macOS),並提供詳盡的文件和教學課程。
架構與技術比較
這些 .NET PDF 函式庫的根本差異在於其輸入格式和技術基礎。
| 範疇 | FO.NET | IronPDF |
|---|---|---|
| 輸入格式 | XSL-FO (過時的 XML) | HTML/CSS (現代網路標準) |
| 學習曲線 | Steep (XSL-FO 專長) | 溫和 (HTML/CSS 知識) |
| 維護 | 棄 | 每月積極維護 |
| 平台支援 | 僅限 Windows | 真正的跨平台 |
| CSS 支援 | 無 | 完整的 CSS3 (Flexbox、Grid) |
| JavaScript。 | 無 | 完整的JavaScript支援 |
| URL 渲染 | 不支援 | 內建 |
| 現代功能 | 限額 | 頁眉、頁腳、水印、安全性 |
| 說明文件 | 過時的 | 全面的教學 |
FO.NET 設計時,XSL-FO 可望成為文件格式的標準。 這並沒有發生-HTML/CSS 成為了通用的文件格式。 大多數 XSL-FO 資源都是 2005-2010 年間的,因此越來越難找到最新的資訊或社群支援。
程式碼比較:常見的 PDF 作業
HTML 至 PDF 轉換
最基本的操作體現了 XSL-FO 和 HTML 方法之間的模型差異。
FO.NET:
// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
using System.Xml;
class Program
{
static void Main()
{
// FoNet requires XSL-FO format, not HTML
// First convert HTML to XSL-FO (manual process)
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='page'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='page'>
<fo:flow flow-name='xsl-region-body'>
<fo:block>Hello World</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("output.pdf", FileMode.Create));
}
}// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
using System.Xml;
class Program
{
static void Main()
{
// FoNet requires XSL-FO format, not HTML
// First convert HTML to XSL-FO (manual process)
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='page'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='page'>
<fo:flow flow-name='xsl-region-body'>
<fo:block>Hello World</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("output.pdf", FileMode.Create));
}
}IronPDF:
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is HTML content.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is HTML content.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}對比很明顯。 FO.NET 要求使用 XML 命名空間聲明、fo:root、fo:layout-master-set、fo:simple-page-master、fo:page-sequence、fo:flow 和 fo:block 元素的冗長 XSL-FO 標記,所有這些都是在產生一個簡單的 "Hello World "文字之前。 程式碼註解明確指出"FoNet需要XSL-FO格式,而非HTML"。
IronPDF 會建立一個渲染器、傳輸標準的 HTML、渲染成 PDF,並使用開發人員已熟悉的語法來節省簡單的行數。
如需進階的 HTML 呈現選項,請探索 HTML 至 PDF 轉換指南。
URL 轉 PDF
將網頁轉換為 PDF 顯示出重要的能力差距。
FO.NET:
// NuGet: Install-Package Fonet
using Fonet;
using System.IO;
using System.Net;
class Program
{
static void Main()
{
// FoNet does not support URL rendering directly
// Must manually download, convert HTML to XSL-FO, then render
string url = "https://example.com";
string html = new WebClient().DownloadString(url);
// Manual conversion from HTML to XSL-FO required (complex)
string xslFo = ConvertHtmlToXslFo(html); // Not built-in
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("webpage.pdf", FileMode.Create));
}
static string ConvertHtmlToXslFo(string html)
{
// Custom implementation required
throw new System.NotImplementedException();
}
}// NuGet: Install-Package Fonet
using Fonet;
using System.IO;
using System.Net;
class Program
{
static void Main()
{
// FoNet does not support URL rendering directly
// Must manually download, convert HTML to XSL-FO, then render
string url = "https://example.com";
string html = new WebClient().DownloadString(url);
// Manual conversion from HTML to XSL-FO required (complex)
string xslFo = ConvertHtmlToXslFo(html); // Not built-in
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("webpage.pdf", FileMode.Create));
}
static string ConvertHtmlToXslFo(string html)
{
// Custom implementation required
throw new System.NotImplementedException();
}
}IronPDF:
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}FO.NET 明確不支援 URL 呈現。 程式碼註解說明:"FoNet 不支援 URL 直接渲染 "和 "需要手動將 HTML 轉換為 XSL-FO(複雜)"。ConvertHtmlToXslFo() 方法會產生 NotImplementedException 錯誤,因為這個轉換不是內建的,需要自訂實作。
IronPDF 提供原生 RenderUrlAsPdf() 功能,可在單一方法呼叫中處理 URL 取用、JavaScript 執行和渲染,僅需三行代碼即可實現複雜、未實現的工作流程。
在 URL to PDF 文件中了解更多關於 URL 渲染的資訊。
具有自訂設定的 PDF 文件
配置頁面尺寸和頁邊空白展示了配置方法的差異。
FO.NET:
// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
class Program
{
static void Main()
{
// FoNet settings are configured in XSL-FO markup
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='A4'
page-height='297mm' page-width='210mm'
margin-top='20mm' margin-bottom='20mm'
margin-left='25mm' margin-right='25mm'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='A4'>
<fo:flow flow-name='xsl-region-body'>
<fo:block font-size='14pt'>Custom PDF</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("custom.pdf", FileMode.Create));
}
}// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
class Program
{
static void Main()
{
// FoNet settings are configured in XSL-FO markup
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='A4'
page-height='297mm' page-width='210mm'
margin-top='20mm' margin-bottom='20mm'
margin-left='25mm' margin-right='25mm'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='A4'>
<fo:flow flow-name='xsl-region-body'>
<fo:block font-size='14pt'>Custom PDF</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("custom.pdf", FileMode.Create));
}
}IronPDF:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 25;
renderer.RenderingOptions.MarginRight = 25;
string html = "<h1 style='font-size:14pt'>Custom PDF</h1>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 25;
renderer.RenderingOptions.MarginRight = 25;
string html = "<h1 style='font-size:14pt'>Custom PDF</h1>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}FO.NET 中的程式碼註解明確指出:"FoNet 設定在 XSL-FO 標記中配置"。頁面大小、頁邊距離和格式化是以 fo:simple-page-master 上的屬性嵌入 XML 結構中。 這意味著配置與內容交織在一起,以冗長的 XML 格式呈現。
IronPDF 使用程式化的 RenderingOptions 屬性將設定與內容分離。 PaperSize, MarginTop, MarginBottom, MarginLeft, 和MarginRight等設定會在渲染器物件上設定,而內容則保持乾淨的 HTML。
API 對應參考。
對於評估 FO.NET 遷移或比較功能的開發人員而言,此對應會顯示等效的操作:
核心類映射
| FO.NET | IronPDF |
|---|---|
| <編碼>FonetDriver.Make()</編碼 | 新的 ChromePdfRenderer() |
driver.Render(inputStream,outputStream)。 | renderer.RenderHtmlAsPdf(html)。 |
driver.Render(inputFile,outputStream)。 | renderer.RenderHtmlFileAsPdf(path)。 |
| <編碼>driver.BaseDirectory</編碼 | RenderingOptions.BaseUrl |
driver.OnError += 處理器。 | 圍繞 render 的 Try/catch |
XSL-FO 至 RenderingOptions 對應
| XSL-FO 屬性 | IronPdf RenderingOptions |
|---|---|
頁高/頁寬 | 紙張大小 |
margin-top | MarginTop |
margin-bottom | 邊界底線 |
margin-left | 邊界左側 |
| <編碼>右邊距</編碼 | MarginRight |
參考導向 | 紙張方向 |
XSL-FO 元素到 HTML 的映射
| XSL-FO 元件 | HTML 對應 |
|---|---|
<fo:root> | <html> |
<fo:layout-master-set> | CSS @page 規則 |
<fo:simple-page-master> | CSS @page |
<fo:page-sequence> | <body> 或 <div> |
| <編碼><fo:流程></編碼 | <main> 或 <div> |
<fo:static-content> | <編碼>HtmlHeaderFooter</編碼 |
<fo:block> | <p>, <div>, <h1>-<h6> |
<fo:table> | <table> |
<fo:list-block> | <ul>、<ol> |
<fo:外部圖形>。 | <編碼> |
<fo:page-number/> | {page} 占位符 |
功能比較摘要
| 特點 | FO.NET | IronPDF |
|---|---|---|
| HTML 至 PDF | ❌(需要手動 XSL-FO 轉換) | ✅ |
| URL 至 PDF | ❌(不支援) | ✅ |
| XSL-FO 至 PDF | ✅ | 不適用 |
| CSS3 支持 | ❌ | ✅ (Flexbox, Grid) |
| JavaScript | ❌ | ✅ |
| 頁首/頁尾 | XSL-FO 靜態內容 | 基於 HTML |
| 頁面編號 | <編碼>fo:page-number</編碼 | {page} 占位符 |
| 跨平台 | ❌(僅限 Windows) | ✅ |
| 主動維護 | ❌(已放棄) | ✅(每月) |
當團隊考慮從 FO.NET 轉移到IronPDF時。
開發團隊評估從 FO.NET 過渡到IronPDF有幾個原因:
過時的技術: XSL-FO 是 W3C 於 2001 年制定的規範,自 2006 年以來一直沒有更新,已被普遍認為過時。 大多數資源和文件都是 2005-2010 年間的,使得尋找最新資訊或僱用具備 XSL-FO 專業知識的開發人員變得越來越困難。
學習曲線陡峭: XSL-FO 需要學習複雜的基於 XML 的標記,以及專門的格式化物件( fo:block 、 fo:table 、 fo:page-sequence等)。 不到 1% 的開發者了解 XSL-FO,而超過 98% 的開發者了解 HTML/CSS。
不支援 HTML/CSS: FO.NET 無法渲染 HTML 或 CSS——它需要手動將 HTML 轉換為 XSL-FO 標記,而該庫中沒有內建此功能。 擁有網頁內容或 HTML 模板的團隊必須執行自訂的轉換邏輯。
已停止維護:原始 CodePlex 儲存庫已失效,GitHub 分支也不再積極維護。 不開發安全修補程式、錯誤修正和新功能。
平台限制: FO.NET 內部依賴 System.Drawing,這使其無法在 Linux/macOS 上運行,從而限制了其部署到僅限 Windows 的環境。 現代應用程式越來越需要跨平台部署。
缺少現代功能:不支援 JavaScript,不支援 CSS3 功能(Flexbox、Grid),不支援現代網頁字體,也不支援直接 URL 渲染功能。
優勢和考慮因素
FO.NET 的優勢
-直接 XSL-FO 轉換:專門針對 XSL-FO 到 PDF 的轉換進行了最佳化 -開源: Apache 2.0 授權—可免費使用、修改和分發 -精確控制: XSL-FO 提供文件佈局的精細控制
FO.NET注意事項
-技術已過時: XSL-FO 規範自 2006 年以來未進行任何更新。 -需要具備 XSL-FO 知識:只有不到 1% 的開發人員精通此技術。 -不支援 HTML:無法渲染 HTML 或 CSS 內容 -已棄用:無任何維護或安全性更新活動 -僅限 Windows 系統: System.Drawing 依賴項阻止了跨平台使用 -不支援URL渲染:無法直接轉換網頁 -文件有限:資源已過時
IronPDF的優勢
IronPDF注意事項
-商業許可:生產用途需要獲得許可 -不同的範式: XSL-FO 模板需要轉換為 HTML
結論
FO.NET 和IronPDF代表了在 .NET 中生成 PDF 的基本不同方法。 FO.NET 服務於 XSL-FO 至 PDF 轉換的利基用例,但其對過時技術的依賴、棄用的維護、僅限於 Windows 的限制,以及缺乏 HTML 支援,使得它越來越難為新專案辯護。
IronPdf 提供使用 HTML/CSS 網路標準的現代方法,符合目前開發人員的技能和技術。 能夠直接呈現 HTML、URL,並使用完整的 CSS3 與 Chromium 引擎,使其適用於當代的 PDF 生成需求。
在組織規劃 .NET 10、C# 14 以及到 2026 年的應用程式開發時,技術基礎非常重要。 維護傳統 XSL-FO 系統的團隊可能會繼續使用 FO.NET,但現代 PDF 生成的前進道路顯然指向IronPDF等基於 HTML 的解決方案,這些解決方案充分利用了現有的網路開發專業知識。