fo.net에서 IronPDF로 마이그레이션하는 방법
fo.net (FO.NET)에서 IronPDF로 마이그레이션은 .NET PDF 생성 과정의 주요 업데이트입니다. 이 가이드는 구식 XSL-FO 마크업에서 최신 HTML/CSS 기반 PDF 생성으로 코드베이스를 전환하는 간단하고 체계적인 경로를 제공합니다. 개발팀이 이미 익숙한 기술을 사용합니다.
fo.net에서 IronPDF로 마이그레이션해야 하는 이유
fo.net의 도전 과제
fo.net은 현재 개발에 여러 제한이 있는 XSL-FO에서 PDF로 렌더러입니다:
-
구식 기술: XSL-FO (확장형 스타일시트 언어 포맷 오브젝트)는 2001년 W3C 표준이며, 2006년 이후 업데이트되지 않았으며 대부분 구식으로 간주됩니다.
-
복잡한 학습 곡선: XSL-FO는 특수한 포맷 객체(
fo:block,fo:table,fo:page-sequence등)를 사용하는 복잡한 XML 기반 마크업을 배워야 합니다. -
HTML/CSS 지원 없음: fo.net은 HTML이나 CSS를 렌더링할 수 없으며, HTML을 XSL-FO 마크업으로 수동 변환이 필요합니다.
-
유지보수 안 됨: 원래의 CodePlex 저장소는 기능을 잃었습니다; GitHub 포크는 더 이상 적극적으로 유지보수 되지 않습니다.
-
윈도우 전용: fo.net은
System.Drawing에 대한 내부 의존성으로 인해 Linux/macOS에서 작동할 수 없습니다. -
제한된 최신 기능:JavaScript지원 없음, CSS3 없음, flexbox/grid 없음, 최신 웹 글꼴 없음.
- URL 렌더링 없음: fo.net은 웹 페이지를 직접 렌더링할 수 없으며, 수동 HTML-to-XSL-FO 변환이 필요합니다.
fo.net vsIronPDF비교
| 측면 | fo.net (FO.NET) | IronPDF |
|---|---|---|
| 입력 형식 | XSL-FO (구식 XML) | HTML/CSS (현대 웹 표준) |
| 학습 곡선 | 급진적인 (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% 이상의 개발자가 알고 있는 문서 형식이 되었으며, XSL-FO를 아는 사람은 1% 미만입니다. 대부분의 XSL-FO 자료는 2005-2010년의 것으로, 유지 보수가 점점 더 어려워지고 있습니다.
IronPDF는 현대의 .NET 버전 (.NET 10 및 C# 14 포함)을 완전히 지원하여 2025년부터 2026년까지 사용 가능한 전문적인 PDF를 만드는 데 이미 가지고 있는 기술을 사용할 수 있게 합니다.
시작하기 전에
필수 조건
- .NET 환경: IronPDF는 .NET Framework 4.6.2+, .NET Core 3.1+, .NET 5/6/7/8/9+를 지원합니다.
- NuGet 액세스: NuGet에서 패키지를 설치할 수 있는지 확인하십시오.
- 라이센스 키: 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 |
렌더 시도/캐치 |
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 @page 규칙 |
|
<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} placeholder |
|
<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 |
16진수, 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로
이전 (fo.net과 XSL-FO):
// 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
이후 (IronPDF와 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에서 PDF로의 옵션에 대해서는 IronPDF HTML에서 PDF로의 문서를 참조하세요.
예제 2: 사용자 정의 설정을 사용한 PDF
이전 (fo.net과 XSL-FO):
// 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
이후 (IronPDF와 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
이후 (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: 헤더와 푸터
이전 (fo.net과 XSL-FO):
<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>
이후 (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는 복잡한 XSL-FO 영역 정의를 간단한 HTML 헤더와 푸터로 대체합니다.
예제 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
이후 (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 FonetIronPdfInstall-Package: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}placeholder로 대체
테스트
- 출력 모습이 원래의 fo.net PDF와 동일한지 비교하세요
- 페이지 크기와 여백을 확인하세요
- 헤더와 푸터를 확인하세요
- 페이지 번호를 검증하세요
- 테이블 렌더링을 테스트하세요
- 이미지 로딩을 확인하세요
마이그레이션 이후
.fo및.xslfo템플릿 파일 삭제- fo.net 관련 코드 및 유틸리티를 제거하세요
- 문서 업데이트
reference](https://ironpdf.com/object-reference/api/).

