fo.net에서 IronPDF로 마이그레이션하는 방법
fo.net (FO.NET)에서 IronPDF로 마이그레이션은 .NET PDF 생성 과정의 주요 업데이트입니다. 이 가이드는 구식 XSL-FO 마크업에서 최신 HTML/CSS 기반 PDF 생성으로 코드베이스를 전환하는 간단하고 체계적인 경로를 제공합니다. 개발팀이 이미 익숙한 기술을 사용합니다.
fo.net에서 IronPDF로 마이그레이션해야 하는 이유
fo.net의 도전 과제
fo.net (FO.NET) 은 XSL-FO 문서를 PDF로 변환하는 초기 Apache FOP 빌드의 C# 포트입니다. 이는 Apache 2.0 라이선스이지만 현재 개발에는 여러 제약이 있습니다:
-
구식 기술: XSL-FO(Extensible Stylesheet Language Formatting Objects)는 2001년 W3C 규격입니다; W3C는 2013년에 XSL-FO 워킹 그룹을 종료했으며 이 언어는 더 이상의 개발이 없습니다.
-
복잡한 학습 곡선: XSL-FO는 복잡한 XML 기반 마크업을 요구하며 전문적인 포맷 객체 (
fo:block,fo:table,fo:page-sequence등)로 구성됩니다. -
HTML/CSS 지원 부족: fo.net은 HTML이나 CSS를 렌더링할 수 없으며, HTML을 직접 XSL-FO로 변환해야 합니다 (일반적으로 XSLT를 통해).
-
버려짐/관리되지 않음: nuget.org의
Fonet패키지는 2011년 4월에 마지막으로 게시되었습니다 (v1.0.0, .NET Framework 2.0). 커뮤니티 포크Fonet.Standard(.NET Standard 2.0)는 2020년 5월에 마지막으로 게시되었습니다 (v1.0.5). CodePlex 저장소는 폐지되었으며 GitHub 포크 (prepare/FO.NET,nholik/FO.Net,hahmed/Fo.Net)는 휴면 상태입니다. -
실질적으로 Windows 전용: 레거시
Fonet빌드는 Windows로 제한되는System.Drawing(GDI+) API에 의존합니다. -
제한된 현대 기능:JavaScript엔진 없음, CSS3 (플렉스박스/그리드) 없음, 현대 웹폰트 로딩 없음.
- URL 렌더링 없음: fo.net은 웹 페이지를 직접 렌더링할 수 없으며, 수동 HTML-to-XSL-FO 변환이 필요합니다.
fo.net vsIronPDF비교
| 측면 | fo.net (FO.NET) | IronPDF |
|---|---|---|
| 입력 형식 | XSL-FO (구식 XML) | HTML/CSS (현대 웹 표준) |
| 학습 곡선 | 급진적인 (XSL-FO 전문성) | 부드러움 (HTML/CSS 지식) |
| 유지보수 | 버려짐 (마지막 릴리스 2020년 5월) | 적극적으로 유지보수됨 |
| 플랫폼 지원 | Windows 전용 | 크로스 플랫폼 (.NET Framework 4.6.2+, .NET Core 3.1+, .NET 5/6/7/8/9+) |
| CSS 지원 | None | 전체 CSS3 (Flexbox, Grid) |
| JavaScript | None | 전체JavaScript지원 |
| URL 렌더링 | 지원되지 않음 | 내장형 |
| 최신 기능 | 제한적 | 머리글, 바닥글, 워터마크, 보안 |
| 문서화 | 구식 | 철저한 튜토리얼 |
전환이 합리적인 이유
fo.net은 XSL-FO가 문서 형식 지정의 표준으로 채택될 것으로 예상될 때 설계되었습니다. 그 기대는 실현되지 않았습니다. HTML/CSS가 범용 문서 포맷이 된 반면, XSL-FO는 틈새 기지가 되었으며 — 대부분의 XSL-FO 자원은 2005–2010에 속해, 유지 관리가 점점 어려워지고 있습니다.
IronPDF은 당신이 이미 가지고 있는 기술로 현대 .NET에서 전문 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 toIronPDF migration"
# Create a backup branch
git checkout -b pre-ironpdf-migration
git add .
git commit -m "Backup before fo.net toIronPDF migration"
모든 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> |
또는 |
|
<fo:flow> |
또는 |
|
<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 |
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> - 단락:
- 일반 컨테이너:
- 인라인 텍스트:
문제 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>HTML문제 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 }$vbLabelText $csharpLabel
마이그레이션 체크리스트
사전 마이그레이션
- 모든 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}플레이스홀더로 대체
테스트
- 출력 모습이 원래의 fo.net PDF와 동일한지 비교하세요
- 페이지 크기와 여백을 확인하세요
- 헤더와 푸터를 확인하세요
- 페이지 번호를 검증하세요
- 테이블 렌더링을 테스트하세요
- 이미지 로딩을 확인하세요
마이그레이션 이후
.fo및.xslfo템플릿 파일 삭제- fo.net 관련 코드 및 유틸리티를 제거하세요
- 문서 업데이트
IronPDF에서 사용된IronPDF표면에 대한 더 깊은 커버리지를 위해 IronPDF API 레퍼런스를 참조하십시오.
참고해 주세요FO.NET, Fonet, 및 Apache FOP는 그 소유자의 상표입니다. 이 사이트는 FO.NET 프로젝트나 Apache Software Foundation과 관련이 없으며, 승인받지 않았고, 후원받지도 않았습니다. 모든 제품명, 로고 및 브랜드는 해당 소유자의 자산입니다. 비교는 정보 제공 목적으로만 사용되며, 작성 시점에 공개적으로 이용 가능한 정보를 반영합니다. - 인라인 텍스트:

