如何從 fo.net 轉移到 IronPDF for .NET
從fo.net (FO.NET)遷移到IronPDF是 .NET PDF 產生流程的重大更新。 本指南提供了一條簡單明了的分步路徑,幫助您利用開發團隊已有的技能,將程式碼庫從過時的 XSL-FO 標記過渡到現代的基於 HTML/CSS 的 PDF 生成。
為什麼要從 fo.net 轉移到 IronPDF?
fo.net 的挑戰
fo.net 是一個 XSL-FO 到 PDF 的渲染器,但目前的開發有一些限制:
1.過時的技術: XSL-FO(可擴展樣式表語言格式化物件)是 W3C 於 2001 年制定的規範,自 2006 年以來沒有更新,因此被普遍認為是過時的。
2.複雜的學習曲線: XSL-FO 需要學習複雜的基於 XML 的標記,以及專門的格式化對象(fo:block、fo:table、fo:page-sequence 等)。
3.不支援 HTML/CSS: fo.net 無法渲染 HTML 或 CSS-需要手動將 HTML 轉換為 XSL-FO 標記。
4.已停止維護:原 CodePlex 程式碼庫已失效; GitHub 分叉已不再積極維護。
5.僅限 Windows: fo.net 對 System.Drawing 有內部依賴關係,這使其無法在 Linux/macOS 上運作。
6.現代功能有限:不支援 JavaScript、CSS3、flexbox/grid、現代網頁字體。
7.不支援 URL 渲染: fo.net 無法直接渲染網頁-需要手動進行 HTML 到 XSL-FO 的轉換。
fo.net vsIronPDF對比。
| 範疇 | fo.net (FO.NET) | IronPDF |
|---|---|---|
| 輸入格式 | XSL-FO(過時的 XML) | HTML/CSS (現代網路標準) |
| 學習曲線 | Steep (XSL-FO 專長) | 溫和 (HTML/CSS 知識) |
| 維護 | 無人維護 | 每月積極維護 |
| 平台支援 | 僅限 Windows | 真正的跨平台(.NET 6/7/8/9/10+) |
| CSS 支援 | 無 | 完整的 CSS3 (Flexbox、Grid) |
| JavaScript | 無 | 完整的JavaScript支援 |
| URL 渲染 | 不支援 | 內建 |
| 現代功能 | 限額 | 頁眉、頁腳、水印、安全性 |
| 文件 | 過時的 | 詳盡的教程 |
為什麼轉換是合理的
fo.net 設計時,XSL-FO 可望成為文件格式的標準。 這個期望從未實現。 HTML/CSS 成為通用的文件格式,超過 98% 的開發人員瞭解 HTML/CSS,而瞭解 XSL-FO 的開發人員則不到 1%。 大多數 XSL-FO 資源的日期為 2005-2010 年間,使得維護變得越來越困難。
IronPDF 可讓您使用已有的技術來製作專業的 PDF,並完全支援現代的 .NET 版本,包括 2025 年至 2026 年上市的 .NET 10 和 C# 14。
開始之前
先決條件
- .NET 環境:IronPDF支援 .NET Framework 4.6.2+、.NET Core 3.1+ 和 .NET 5/6/7/8/9+。
- NuGet 存取權限:確保您可以從 NuGet 安裝套件。 3.許可證密鑰:請從ironpdf.com取得用於生產環境的IronPDF許可證密鑰。
備份您的專案
# Create a backup branch
git checkout -b pre-ironpdf-migration
git add .
git commit -m "Backup before fo.net toIronPDFmigration"
# Create a backup branch
git checkout -b pre-ironpdf-migration
git add .
git commit -m "Backup before fo.net toIronPDFmigration"
辨識所有 fo.net 使用方式
# Find all fo.net references
grep -r "FonetDriver\|Fonet\|\.fo\"\|xsl-region" --include="*.cs" --include="*.csproj" .
# Find all XSL-FO template files
find . -name "*.fo" -o -name "*.xslfo" -o -name "*xsl-fo*"
# Find all fo.net references
grep -r "FonetDriver\|Fonet\|\.fo\"\|xsl-region" --include="*.cs" --include="*.csproj" .
# Find all XSL-FO template files
find . -name "*.fo" -o -name "*.xslfo" -o -name "*xsl-fo*"
記錄您的 XSL-FO 範本
在轉換之前,將所有 XSL-FO 檔案編目並備註:
- 頁面尺寸與頁邊
- 使用的字體
- 表格及其結構
- 頁首和頁尾(
fo:static-content) - 頁面編號模式
- 圖片參考
快速啟動遷移
步驟 1:更新 NuGet 套件
# Remove fo.net package
dotnet remove package Fonet
dotnet remove package FO.NET
# Install IronPDF
dotnet add package IronPdf
# Remove fo.net package
dotnet remove package Fonet
dotnet remove package FO.NET
# Install IronPDF
dotnet add package IronPdf
步驟 2:更新命名空間
// Before (fo.net)
using Fonet;
using Fonet.Render.Pdf;
using System.Xml;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
// Before (fo.net)
using Fonet;
using Fonet.Render.Pdf;
using System.Xml;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
Imports IronPdf
Imports IronPdf.Rendering
步驟 3:初始化 IronPDF
// Set license key at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Set license key at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Set license key at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
步驟 4:基本轉換模式
// Before (fo.net with XSL-FO)
FonetDriver driver = FonetDriver.Make();
using (FileStream output = new FileStream("output.pdf", FileMode.Create))
{
driver.Render(new StringReader(xslFoContent), output);
}
// After (IronPDF with HTML)
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
// Before (fo.net with XSL-FO)
FonetDriver driver = FonetDriver.Make();
using (FileStream output = new FileStream("output.pdf", FileMode.Create))
{
driver.Render(new StringReader(xslFoContent), output);
}
// After (IronPDF with HTML)
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
Imports System.IO
Imports Fonet
Imports IronPdf
' Before (fo.net with XSL-FO)
Dim driver As FonetDriver = FonetDriver.Make()
Using output As FileStream = New FileStream("output.pdf", FileMode.Create)
driver.Render(New StringReader(xslFoContent), output)
End Using
' After (IronPDF with HTML)
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
完整的 API 參考資料
命名空間對應
| fo.net 命名空間 | IronPDF 同等級產品 |
|---|---|
Fonet |
IronPdf |
Fonet.Render.Pdf |
IronPdf |
Fonet.Layout |
不適用 |
Fonet.Fo |
不適用 |
Fonet.Image |
IronPdf |
FonetDriver 至 ChromePdfRenderer。
| FonetDriver 方法 | IronPDF 同等級產品 |
|---|---|
FonetDriver.Make() |
new ChromePdfRenderer() |
driver.Render(inputStream, outputStream) |
renderer.RenderHtmlAsPdf(html) |
driver.Render(inputFile, outputStream) |
renderer.RenderHtmlFileAsPdf(path) |
driver.BaseDirectory |
RenderingOptions.BaseUrl |
driver.OnError += handler |
圍繞 render 的 Try/catch |
RenderingOptions(PDF 配置)
| fo.net (XSL-FO 屬性) | IronPDF RenderingOptions |
|---|---|
page-height |
PaperSize 或 SetCustomPaperSize() |
page-width |
PaperSize |
margin-top |
MarginTop |
margin-bottom |
MarginBottom |
margin-left |
MarginLeft |
margin-right |
MarginRight |
reference-orientation |
PaperOrientation |
XSL-FO 至 HTML 轉換指南
XSL-FO 元件轉換為 HTML/CSS
這次 fo.net 移植的基本轉換是將 XSL-FO 元素轉換為其 HTML 對應元素:
| XSL-FO 元件 | HTML/CSS 對應 | |
|---|---|---|
<fo:root> |
<html> |
|
<fo:layout-master-set> |
CSS 規則 | |
<fo:simple-page-master> |
CSS @page |
|
<fo:page-sequence> |
<body> 或 <div> |
|
<fo:flow> |
<main> 或 <div> |
|
<fo:static-content> |
HtmlHeaderFooter |
|
<fo:block> |
<p>, <div>, <h1>-<h6> |
|
<fo:inline> |
<span> |
|
<fo:table> |
<table> |
|
<fo:table-row> |
<tr> |
|
<fo:table-cell> |
<td>, <th> |
|
<fo:list-block> |
<ul>, <ol> |
|
<fo:list-item> |
<li> |
|
<fo:external-graphic> |
<img> |
|
<fo:page-number> |
{page}佔位符 |
|
<fo:page-number-citation> |
{total-pages} |
|
<fo:basic-link> |
<a href> |
XSL-FO 屬性轉換為 CSS
| XSL-FO 特性 | CSS 對應 | 範例 |
|---|---|---|
font-family |
font-family |
相同的語法 |
font-size |
font-size |
相同的語法 |
font-weight |
font-weight |
bold, normal, 700 |
text-align |
text-align |
left, center, right, justify |
color |
color |
十六進制、RGB、名稱 |
background-color |
background-color |
相同的語法 |
space-before |
margin-top |
元素之前 |
space-after |
margin-bottom |
元素之後 |
start-indent |
margin-left |
左縮 |
keep-together |
page-break-inside: avoid |
防止中斷 |
break-before="page" |
page-break-before: always |
強制分頁 |
程式碼範例
範例 1:基本 HTML 到 PDF
之前(使用 XSL-FO 的 fo.net):
// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
using System.Xml;
class Program
{
static void Main()
{
// fo.net 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()
{
// fo.net 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));
}
}
Imports Fonet
Imports Fonet.Render.Pdf
Imports System.IO
Imports System.Xml
Module Program
Sub Main()
' fo.net requires XSL-FO format, not HTML
' First convert HTML to XSL-FO (manual process)
Dim xslFo As String = "<?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>"
Dim driver As FonetDriver = FonetDriver.Make()
driver.Render(New StringReader(xslFo),
New FileStream("output.pdf", FileMode.Create))
End Sub
End Module
After (IronPDF with HTML):
// 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");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html As String = "<h1>Hello World</h1><p>This is HTML content.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class
IronPDF 方法將 25 行以上的 XSL-FO 標記減少至僅 4 行乾淨的 C# 程式碼。 如需更多 HTML to PDF 選項,請參閱 IronPDF HTML to PDF 文件。
範例 2:自訂設定的 PDF
之前(使用 XSL-FO 的 fo.net):
// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
class Program
{
static void Main()
{
// fo.net 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()
{
// fo.net 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));
}
}
Imports Fonet
Imports Fonet.Render.Pdf
Imports System.IO
Class Program
Shared Sub Main()
' fo.net settings are configured in XSL-FO markup
Dim xslFo As String = "<?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>"
Dim driver As FonetDriver = FonetDriver.Make()
driver.Render(New StringReader(xslFo),
New FileStream("custom.pdf", FileMode.Create))
End Sub
End Class
After (IronPDF with HTML):
// 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");
}
}
Imports IronPdf
Imports IronPdf.Engines.Chrome
Class Program
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
renderer.RenderingOptions.MarginLeft = 25
renderer.RenderingOptions.MarginRight = 25
Dim html As String = "<h1 style='font-size:14pt'>Custom PDF</h1>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("custom.pdf")
End Sub
End Class
IronPDF 提供程式化的 渲染選項,而非在 XML 標記中嵌入設定。
範例 3:URL 至 PDF
之前 (fo.net - 不支援):
// NuGet: Install-Package Fonet
using Fonet;
using System.IO;
using System.Net;
class Program
{
static void Main()
{
// fo.net 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 - extremely complex
throw new System.NotImplementedException();
}
}
// NuGet: Install-Package Fonet
using Fonet;
using System.IO;
using System.Net;
class Program
{
static void Main()
{
// fo.net 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 - extremely complex
throw new System.NotImplementedException();
}
}
Imports Fonet
Imports System.IO
Imports System.Net
Class Program
Shared Sub Main()
' fo.net does not support URL rendering directly
' Must manually download, convert HTML to XSL-FO, then render
Dim url As String = "https://example.com"
Dim html As String = New WebClient().DownloadString(url)
' Manual conversion from HTML to XSL-FO required (complex)
Dim xslFo As String = ConvertHtmlToXslFo(html) ' Not built-in
Dim driver As FonetDriver = FonetDriver.Make()
driver.Render(New StringReader(xslFo),
New FileStream("webpage.pdf", FileMode.Create))
End Sub
Shared Function ConvertHtmlToXslFo(html As String) As String
' Custom implementation required - extremely complex
Throw New System.NotImplementedException()
End Function
End Class
After (IronPDF - 內建支援):(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");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
URL 到 PDF 的渲染是此次 fo.net 移植中最顯著的優勢之一。IronPDF透過完整的JavaScript執行原生處理。 進一步瞭解 URL 至 PDF 轉換。
範例 4:頁首和頁尾
之前(使用 XSL-FO 的 fo.net):
<fo:static-content flow-name="xsl-region-before">
<fo:block text-align="center" font-size="10pt">
Company Name - Confidential
</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block text-align="right" font-size="10pt">
Page <fo:page-number/> of <fo:page-number-citation ref-id="last-page"/>
</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-before">
<fo:block text-align="center" font-size="10pt">
Company Name - Confidential
</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block text-align="right" font-size="10pt">
Page <fo:page-number/> of <fo:page-number-citation ref-id="last-page"/>
</fo:block>
</fo:static-content>
After (IronPDF):
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center; font-size:10pt;'>Company Name - Confidential</div>",
DrawDividerLine = true
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:right; font-size:10pt;'>Page {page} of {total-pages}</div>",
DrawDividerLine = true
};
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center; font-size:10pt;'>Company Name - Confidential</div>",
DrawDividerLine = true
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:right; font-size:10pt;'>Page {page} of {total-pages}</div>",
DrawDividerLine = true
};
Imports System
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter() With {
.HtmlFragment = "<div style='text-align:center; font-size:10pt;'>Company Name - Confidential</div>",
.DrawDividerLine = True
}
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter() With {
.HtmlFragment = "<div style='text-align:right; font-size:10pt;'>Page {page} of {total-pages}</div>",
.DrawDividerLine = True
}
IronPDF 以簡單的 HTML 標頭和頁尾取代複雜的 XSL-FO 區域定義。
範例 5:PDF 安全性
之前 (fo.net):
// fo.net has very limited PDF security options
// Must use post-processing with another library
// fo.net has very limited PDF security options
// Must use post-processing with another library
' fo.net has very limited PDF security options
' Must use post-processing with another library
After (IronPDF):
using IronPdf;
public byte[] GenerateSecurePdf(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Set metadata
pdf.MetaData.Title = "Confidential Report";
pdf.MetaData.Author = "Company Name";
// Password protection
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user456";
// Restrict permissions
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserEdits = IronPdf.Security.PdfEditSecurity.NoEdit;
return pdf.BinaryData;
}
using IronPdf;
public byte[] GenerateSecurePdf(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Set metadata
pdf.MetaData.Title = "Confidential Report";
pdf.MetaData.Author = "Company Name";
// Password protection
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user456";
// Restrict permissions
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserEdits = IronPdf.Security.PdfEditSecurity.NoEdit;
return pdf.BinaryData;
}
Imports IronPdf
Public Function GenerateSecurePdf(html As String) As Byte()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
' Set metadata
pdf.MetaData.Title = "Confidential Report"
pdf.MetaData.Author = "Company Name"
' Password protection
pdf.SecuritySettings.OwnerPassword = "owner123"
pdf.SecuritySettings.UserPassword = "user456"
' Restrict permissions
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.NoPrint
pdf.SecuritySettings.AllowUserEdits = IronPdf.Security.PdfEditSecurity.NoEdit
Return pdf.BinaryData
End Function
效能考量
重複使用 ChromePdfRenderer
為了在 fo.net 遷移期間獲得最佳效能,請重複使用 ChromePdfRenderer 實例:
// GOOD - Reuse the renderer
public class PdfService
{
private static readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();
public byte[] Generate(string html) => _renderer.RenderHtmlAsPdf(html).BinaryData;
}
// BAD - Creating new instance each time
public byte[] GenerateBad(string html)
{
var renderer = new ChromePdfRenderer(); // Wasteful
return renderer.RenderHtmlAsPdf(html).BinaryData;
}
// GOOD - Reuse the renderer
public class PdfService
{
private static readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();
public byte[] Generate(string html) => _renderer.RenderHtmlAsPdf(html).BinaryData;
}
// BAD - Creating new instance each time
public byte[] GenerateBad(string html)
{
var renderer = new ChromePdfRenderer(); // Wasteful
return renderer.RenderHtmlAsPdf(html).BinaryData;
}
Imports System
' GOOD - Reuse the renderer
Public Class PdfService
Private Shared ReadOnly _renderer As New ChromePdfRenderer()
Public Function Generate(html As String) As Byte()
Return _renderer.RenderHtmlAsPdf(html).BinaryData
End Function
End Class
' BAD - Creating new instance each time
Public Function GenerateBad(html As String) As Byte()
Dim renderer As New ChromePdfRenderer() ' Wasteful
Return renderer.RenderHtmlAsPdf(html).BinaryData
End Function
單元轉換輔助工具
fo.net XSL-FO 使用多種單位。IronPDF使用毫米作為頁邊。 這裡有一個輔助類:
public static class UnitConverter
{
public static double InchesToMm(double inches) => inches * 25.4;
public static double PointsToMm(double points) => points * 0.352778;
public static double PicasToMm(double picas) => picas * 4.233;
public static double CmToMm(double cm) => cm * 10;
}
// Usage
renderer.RenderingOptions.MarginTop = UnitConverter.InchesToMm(1); // 1 inch
public static class UnitConverter
{
public static double InchesToMm(double inches) => inches * 25.4;
public static double PointsToMm(double points) => points * 0.352778;
public static double PicasToMm(double picas) => picas * 4.233;
public static double CmToMm(double cm) => cm * 10;
}
// Usage
renderer.RenderingOptions.MarginTop = UnitConverter.InchesToMm(1); // 1 inch
Public Module UnitConverter
Public Function InchesToMm(inches As Double) As Double
Return inches * 25.4
End Function
Public Function PointsToMm(points As Double) As Double
Return points * 0.352778
End Function
Public Function PicasToMm(picas As Double) As Double
Return picas * 4.233
End Function
Public Function CmToMm(cm As Double) As Double
Return cm * 10
End Function
End Module
' Usage
renderer.RenderingOptions.MarginTop = UnitConverter.InchesToMm(1) ' 1 inch
疑難排解
問題 1:頁面大小的差異
問題: fo.net 遷移後 PDF 頁面大小顯示異常。
解決方案:正確對應 XSL-FO 頁面尺寸:
// XSL-FO: page-height='11in' page-width='8.5in' (Letter)
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
// XSL-FO: page-height='297mm' page-width='210mm' (A4)
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
// Custom size (in mm)
renderer.RenderingOptions.SetCustomPaperSize(210, 297);
// XSL-FO: page-height='11in' page-width='8.5in' (Letter)
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
// XSL-FO: page-height='297mm' page-width='210mm' (A4)
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
// Custom size (in mm)
renderer.RenderingOptions.SetCustomPaperSize(210, 297);
' XSL-FO: page-height='11in' page-width='8.5in' (Letter)
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
' XSL-FO: page-height='297mm' page-width='210mm' (A4)
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
' Custom size (in mm)
renderer.RenderingOptions.SetCustomPaperSize(210, 297)
問題 2:fo:block 到 HTML 的映射
問題:不確定 <fo:block> 應該變成什麼。
解決方案:使用適當的語意化 HTML:
- 標題:
<h1>至<h6> - 段落:
<p> - 通用容器:
<div> - 內嵌文字:
<span>
問題 3:字型不匹配
問題:字體與 fo.net 輸出的字體看起來不一樣。
解決方案:使用網頁字體或在 CSS 中指定係統字體:
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
body { font-family: 'Roboto', Arial, sans-serif; }
</style>
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
body { font-family: 'Roboto', Arial, sans-serif; }
</style>
問題 4:頁碼無法正常運作
問題: <fo:page-number/> 不起作用。
解決方案:在頁首/頁尾中使用IronPDF佔位符:
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center;'>Page {page} of {total-pages}</div>",
MaxHeight = 15 // mm
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center;'>Page {page} of {total-pages}</div>",
MaxHeight = 15 // mm
};
Imports System
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter() With {
.HtmlFragment = "<div style='text-align:center;'>Page {page} of {total-pages}</div>",
.MaxHeight = 15 ' mm
}
遷移清單
預遷移
- 將所有 XSL-FO 範本檔案編目(
.fo,.xslfo) - 文件頁面尺寸和邊距
- 注意頁首/頁尾設定(
fo:static-content) - 確定表格結構和样式
- 將項目備份到版本控制系統
- 取得IronPDF許可證密鑰
套件遷移
- 移除
Fonet或FO.NET軟體包:dotnet remove package Fonet - 安裝
IronPdf軟體包:dotnet add package IronPdf - 將命名空間匯入從
Fonet更新為IronPdf - 啟動時設定IronPDF許可證密鑰
程式碼遷移
- 將
FonetDriver.Make()替換為new ChromePdfRenderer() - 將
driver.Render()替換為renderer.RenderHtmlAsPdf() - 將流中的檔案輸出更新為
pdf.SaveAs() - 將錯誤事件處理程序替換為 try/catch
- 將
fo:static-content轉換為HtmlHeaderFooter - 將
<fo:page-number/>替換為{page}佔位符
測試
- 將輸出外觀與原始 fo.net PDF 進行比較
- 檢查頁面尺寸和邊距。
- 檢查頁首和頁尾
- 驗證頁碼
- 測試表格渲染
- 驗證映像載入情況
後遷移
- 刪除
.fo和.xslfo範本文件 - 移除與 fo.net 相關的程式碼和實用程式
- 更新文件

