푸터 콘텐츠로 바로가기
마이그레이션 가이드

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 라이선스이지만 현재 개발에는 여러 제약이 있습니다:

  1. 구식 기술: XSL-FO(Extensible Stylesheet Language Formatting Objects)는 2001년 W3C 규격입니다; W3C는 2013년에 XSL-FO 워킹 그룹을 종료했으며 이 언어는 더 이상의 개발이 없습니다.

  2. 복잡한 학습 곡선: XSL-FO는 복잡한 XML 기반 마크업을 요구하며 전문적인 포맷 객체 (fo:block, fo:table, fo:page-sequence 등)로 구성됩니다.

  3. HTML/CSS 지원 부족: fo.net은 HTML이나 CSS를 렌더링할 수 없으며, HTML을 직접 XSL-FO로 변환해야 합니다 (일반적으로 XSLT를 통해).

  4. 버려짐/관리되지 않음: 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)는 휴면 상태입니다.

  5. 실질적으로 Windows 전용: 레거시 Fonet 빌드는 Windows로 제한되는 System.Drawing (GDI+) API에 의존합니다.

  6. 제한된 현대 기능:JavaScript엔진 없음, CSS3 (플렉스박스/그리드) 없음, 현대 웹폰트 로딩 없음.

  7. 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를 만들 수 있게 합니다.


시작하기 전에

필수 조건

  1. .NET 환경: IronPDF는 .NET Framework 4.6.2+, .NET Core 3.1+, .NET 5/6/7/8/9+를 지원합니다.
  2. 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 toIronPDF migration"
# Create a backup branch
git checkout -b pre-ironpdf-migration
git add .
git commit -m "Backup before fo.net toIronPDF migration"
SHELL

모든 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*"
SHELL

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
SHELL

단계 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
$vbLabelText   $csharpLabel

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"
$vbLabelText   $csharpLabel

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")
$vbLabelText   $csharpLabel

완전한 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
$vbLabelText   $csharpLabel

이후 (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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

이후 (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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

이후 (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
$vbLabelText   $csharpLabel

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>
XML

이후 (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
}
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

이후 (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
$vbLabelText   $csharpLabel

성능 고려 사항

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
$vbLabelText   $csharpLabel

단위 변환 도우미

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
$vbLabelText   $csharpLabel

문제 해결

문제 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)
$vbLabelText   $csharpLabel

문제 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 Fonet
  • IronPdf Install-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과 관련이 없으며, 승인받지 않았고, 후원받지도 않았습니다. 모든 제품명, 로고 및 브랜드는 해당 소유자의 자산입니다. 비교는 정보 제공 목적으로만 사용되며, 작성 시점에 공개적으로 이용 가능한 정보를 반영합니다.

Curtis Chau
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해