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

Rotativa에서 IronPDF로의 마이그레이션 방법 (C#)

Rotativa에서 IronPDF로 마이그레이션하면 중요한 보안 취약점을 해결하면서 PDF 생성 워크플로우를 현대화합니다. 이 가이드는 포기된 wkhtmltopdf 의존성을 제거하고, 최신 CSS 및 JavaScript 지원을 가능하게 하며 ASP.NET MVC를 넘어 크로스 플랫폼 호환성을 제공하는 완전한 단계별 마이그레이션 경로를 제공합니다.

왜 Rotativa에서 IronPDF로 마이그레이션해야 하는가

Rotativa이해하기

Rotativa는 C#에서 PDF 생성을 위해 개발자들 사이에서 오랫동안 인기 있는 선택이었습니다. HTML 내용을 PDF 형식으로 변환하기 위해 wkhtmltopdf 도구를 활용합니다. Rotativa는 ASP.NET MVC 애플리케이션을 위해 특별히 설계된 오픈 소스 라이브러리입니다. 그러나 상당한 사용자를 끌어들이는 동안, Rotativa가 구식 기술 스택에 의존하고 있다는 점은 모든 개발자에게 즉각적으로 명확하지 않을 수 있는 문제가 됩니다.

근본적으로 Rotativa는 PDF 생성을 ASP.NET MVC 프로젝트에 통합하는 간단한 방법을 제공하며, 이를 위한 백엔드 기능에는 wkhtmltopdf를 이용합니다.

중대한 보안 권고

Rotativa는 해결되지 않은 중대한 보안 취약점을 가진 wkhtmltopdf를 포함합니다.

속성
CVE ID CVE-2022-35583
심각도 심각한 (9.8/10)
공격 벡터 네트워크
상태 절대 패치되지 않음
영향을 받음 모든Rotativa버전

wkhtmltopdf는 2022년 12월에 공식적으로 포기되었습니다. 유지 관리자들은 보안 취약점을 수정하지 않을 것이라고 명시적으로 밝혔습니다. Rotativa를 사용하는 모든 애플리케이션은 영구적으로 노출됩니다.

공격 작동 방식


<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin" />

<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin" />
HTML

영향:

  • AWS/Azure/GCP 클라우드 메타데이터 엔드포인트에 접근
  • 내부 API 데이터 및 자격증명 탈취
  • 내부 네트워크 포트 스캔
  • 민감한 구성 정보 유출

기술 위기

Rotativa는 wkhtmltopdf를 감싸고 있으며, 이를 사용하는 기술들:

  • Qt WebKit 4.8 (2012년)
  • Flexbox 지원 없음
  • CSS Grid 지원 없음
  • JavaScript 실행 오류
  • ES6+ 지원 없음

Rotativa와IronPDF비교

기능 Rotativa IronPDF
프로젝트 호환성 ASP.NET MVC 전용 모든 .NET 프로젝트 유형 (MVC, Razor Pages, Blazor 등)
유지보수 버려짐 활발히 유지 관리됨
보안 wkhtmltopdf 종속성으로 인한 취약성 (CVE-2022-35583) 정기적인 업데이트 및 보안 패치
HTML 렌더링 구식 WebKit 최신 크로뮴
CSS3 부분적 지원됨
플렉스박스/그리드 지원되지 않음 지원됨
JavaScript 신뢰할 수 없음 전체 ES6+
Razor Pages 지원되지 않음 지원됨
Blazor 지원되지 않음 지원됨
PDF 조작 사용 불가 전체
디지털 서명 사용 불가 전체
PDF/A 준수 사용 불가 전체
Async/Await 동기식만 완전 비동기
오픈 소스 예, MIT 라이선스 아니요, 상업용 라이선스

.NET 10 및 C# 14 채택을 계획 중인 팀을 위해 IronPDF는 Rotativa가 제공할 수 없는 현대적 Chrome 렌더링 및 플랫폼 간 지원을 제공합니다.


시작하기 전에

필수 조건

  1. .NET 환경: .NET Framework 4.6.2+ 또는 .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet 접근 권한: NuGet 패키지를 설치할 수 있는 능력
  3. IronPDF 라이선스: ironpdf.com에서 라이선스 키를 획득하세요

NuGet 패키지 변경 사항

# Remove Rotativa
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore

# Install IronPDF
dotnet add package IronPdf
# Remove Rotativa
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore

# Install IronPDF
dotnet add package IronPdf
SHELL

wkhtmltopdf 바이너리 제거

프로젝트에서 다음 파일을 삭제하세요:

  • wkhtmltopdf.exe
  • wkhtmltox.dll
  • 모든 Rotativa/ 폴더

이 파일들이 CVE-2022-35583의 원인입니다. IronPDF는 네이티브 바이너리가 필요하지 않습니다.

라이선스 구성

// Add in Program.cs or Startup.cs
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add in Program.cs or Startup.cs
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add in Program.vb or Startup.vb
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

완전한 API 참조

네임스페이스 변경

// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
' Before: Rotativa
Imports Rotativa
Imports Rotativa.Options
Imports Rotativa.AspNetCore

' After: IronPDF
Imports IronPdf
Imports IronPdf.Rendering
$vbLabelText   $csharpLabel

핵심 클래스 매핑

Rotativa클래스 IronPDF 동등
ViewAsPdf ChromePdfRenderer
ActionAsPdf ChromePdfRenderer.RenderUrlAsPdf()
UrlAsPdf ChromePdfRenderer.RenderUrlAsPdf()
Orientation 열거형 PdfPaperOrientation 열거형
Size 열거형 PdfPaperSize 열거형

페이지 자리 표시자 변환

Rotativa플레이스홀더 IronPDF 플레이스홀더
[page] {page}
[topage] {total-pages}
[date] {date}
[time] {time}
[title] {html-title}
[sitepage] {url}

코드 마이그레이션 예제

예제 1: HTML에서 PDF로 변환

이전 (Rotativa):

// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class PdfController : Controller
    {
        public async Task<IActionResult> GeneratePdf()
        {
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            //Rotativarequires returning a ViewAsPdf result from MVC controller
            return new ViewAsPdf()
            {
                ViewName = "PdfView",
                PageSize = Rotativa.AspNetCore.Options.Size.A4
            };
        }
    }
}
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class PdfController : Controller
    {
        public async Task<IActionResult> GeneratePdf()
        {
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            //Rotativarequires returning a ViewAsPdf result from MVC controller
            return new ViewAsPdf()
            {
                ViewName = "PdfView",
                PageSize = Rotativa.AspNetCore.Options.Size.A4
            };
        }
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks

Namespace RotativaExample
    Public Class PdfController
        Inherits Controller

        Public Async Function GeneratePdf() As Task(Of IActionResult)
            Dim htmlContent As String = "<h1>Hello World</h1><p>This is a PDF document.</p>"

            ' Rotativa requires returning a ViewAsPdf result from MVC controller
            Return New ViewAsPdf() With {
                .ViewName = "PdfView",
                .PageSize = Rotativa.AspNetCore.Options.Size.A4
            }
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

이후 (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("output.pdf");

            Console.WriteLine("PDF generated successfully!");
        }
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();
            var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";

            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("output.pdf");

            Console.WriteLine("PDF generated successfully!");
        }
    }
}
Imports IronPdf
Imports System

Namespace IronPdfExample
    Class Program
        Shared Sub Main(ByVal args As String())
            Dim renderer = New ChromePdfRenderer()
            Dim htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>"

            Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
            pdf.SaveAs("output.pdf")

            Console.WriteLine("PDF generated successfully!")
        End Sub
    End Class
End Namespace
$vbLabelText   $csharpLabel

이 예제는 근본적인 아키텍처 차이를 보여줍니다. Rotativa는 MVC 컨트롤러 액션에서 ViewAsPdf 결과를 반환하여 ASP.NET MVC 프레임워크와 연결됩니다. 이 패턴은 MVC 요청 파이프라인 내에서만 작동하며 Razor 뷰를 렌더링하기 위해 필요합니다.

IronPDF는 콘솔 애플리케이션, 웹 API, Blazor, Razor Pages 또는 모든 .NET 프로젝트 유형에서 작동합니다. HTML 문자열을 사용하여 RenderHtmlAsPdf()을 호출하고 결과를 저장합니다. MVC 컨트롤러가 필요 없으며, 뷰 종속성이 없습니다. HTML에서 PDF로의 문서에서 포괄적인 예제를 참조하세요.

예제 2: URL에서 PDF로 변환

이전 (Rotativa):

// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class UrlPdfController : Controller
    {
        public async Task<IActionResult> ConvertUrlToPdf()
        {
            //Rotativaworks within MVC framework and returns ActionResult
            return new UrlAsPdf("https://www.example.com")
            {
                FileName = "webpage.pdf",
                PageSize = Rotativa.AspNetCore.Options.Size.A4,
                PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
            };
        }
    }
}
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class UrlPdfController : Controller
    {
        public async Task<IActionResult> ConvertUrlToPdf()
        {
            //Rotativaworks within MVC framework and returns ActionResult
            return new UrlAsPdf("https://www.example.com")
            {
                FileName = "webpage.pdf",
                PageSize = Rotativa.AspNetCore.Options.Size.A4,
                PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
            };
        }
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks

Namespace RotativaExample
    Public Class UrlPdfController
        Inherits Controller

        Public Async Function ConvertUrlToPdf() As Task(Of IActionResult)
            ' Rotativa works within MVC framework and returns ActionResult
            Return New UrlAsPdf("https://www.example.com") With {
                .FileName = "webpage.pdf",
                .PageSize = Rotativa.AspNetCore.Options.Size.A4,
                .PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
            }
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

이후 (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
            pdf.SaveAs("webpage.pdf");

            Console.WriteLine("URL converted to PDF successfully!");
        }
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
            pdf.SaveAs("webpage.pdf");

            Console.WriteLine("URL converted to PDF successfully!");
        }
    }
}
Imports IronPdf
Imports System

Namespace IronPdfExample
    Class Program
        Shared Sub Main(ByVal args As String())
            Dim renderer = New ChromePdfRenderer()

            Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
            pdf.SaveAs("webpage.pdf")

            Console.WriteLine("URL converted to PDF successfully!")
        End Sub
    End Class
End Namespace
$vbLabelText   $csharpLabel

Rotativa의 UrlAsPdf 클래스는 MVC 컨트롤러에서 ActionResult 반환을 요구합니다. IronPDF의 RenderUrlAsPdf() 메소드는 모든 컨텍스트에서 호출할 수 있으며 PdfDocument 객체를 직접 반환합니다. URL 렌더링은 wkhtmltopdf의 취약하고 구식인 WebKit 엔진 대신 현대적 Chrome을 사용합니다. 자세한 내용은 튜토리얼을 참조하세요.

예제 3: 페이지 번호가 있는 헤더와 푸터

이전 (Rotativa):

// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class HeaderFooterController : Controller
    {
        public async Task<IActionResult> GeneratePdfWithHeaderFooter()
        {
            return new ViewAsPdf("Report")
            {
                PageSize = Size.A4,
                PageMargins = new Margins(20, 10, 20, 10),
                CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [toPage]\""
            };
        }
    }
}
// NuGet: Install-Package Rotativa.Core
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;

namespace RotativaExample
{
    public class HeaderFooterController : Controller
    {
        public async Task<IActionResult> GeneratePdfWithHeaderFooter()
        {
            return new ViewAsPdf("Report")
            {
                PageSize = Size.A4,
                PageMargins = new Margins(20, 10, 20, 10),
                CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [toPage]\""
            };
        }
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports Rotativa.AspNetCore.Options
Imports System.Threading.Tasks

Namespace RotativaExample
    Public Class HeaderFooterController
        Inherits Controller

        Public Async Function GeneratePdfWithHeaderFooter() As Task(Of IActionResult)
            Return New ViewAsPdf("Report") With {
                .PageSize = Size.A4,
                .PageMargins = New Margins(20, 10, 20, 10),
                .CustomSwitches = "--header-center ""Page Header"" --footer-center ""Page [page] of [toPage]"""
            }
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

이후 (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
            {
                CenterText = "Page Header",
                DrawDividerLine = true
            };

            renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
            {
                CenterText = "Page {page} of {total-pages}",
                DrawDividerLine = true
            };

            var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("report.pdf");

            Console.WriteLine("PDF with headers and footers created successfully!");
        }
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

namespace IronPdfExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var renderer = new ChromePdfRenderer();

            renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
            {
                CenterText = "Page Header",
                DrawDividerLine = true
            };

            renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
            {
                CenterText = "Page {page} of {total-pages}",
                DrawDividerLine = true
            };

            var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            pdf.SaveAs("report.pdf");

            Console.WriteLine("PDF with headers and footers created successfully!");
        }
    }
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System

Namespace IronPdfExample
    Class Program
        Shared Sub Main(ByVal args As String())
            Dim renderer = New ChromePdfRenderer()

            renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
                .CenterText = "Page Header",
                .DrawDividerLine = True
            }

            renderer.RenderingOptions.TextFooter = New TextHeaderFooter() With {
                .CenterText = "Page {page} of {total-pages}",
                .DrawDividerLine = True
            }

            Dim htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>"
            Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
            pdf.SaveAs("report.pdf")

            Console.WriteLine("PDF with headers and footers created successfully!")
        End Sub
    End Class
End Namespace
$vbLabelText   $csharpLabel

Rotativa는 명령줄 인수를 wkhtmltopdf에 전달하기 위해 CustomSwitches를 사용하며, [page][toPage]와 같은 플레이스홀더를 포함한 헤더 및 푸터 구성을 제공합니다. 이 문자열 기반 접근 방식은 오류 발생 가능성이 높으며 컴파일 시 유효성을 검사하기 어렵습니다.

IronPDF는 CenterTextDrawDividerLine와 같은 속성을 가진 강력한 형식의 TextHeaderFooter 객체를 사용합니다. 플레이스홀더 문법이 [page]에서 {page}로, [toPage]에서 {total-pages}로 변경됩니다. 타입이 지정된 속성은 IntelliSense, 컴파일 시 검사, 오타의 위험 없음 등을 제공합니다.


MVC 전용 아키텍처 문제

Rotativa는 ASP.NET MVC 5 및 이전 버전용으로 설계되었습니다:

// ❌Rotativa- Only works with classic MVC pattern
public class InvoiceController : Controller
{
    public ActionResult InvoicePdf(int id)
    {
        var model = GetInvoice(id);
        return new ViewAsPdf("Invoice", model);  // Tied to MVC Views
    }
}

// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integration
// ❌Rotativa- Only works with classic MVC pattern
public class InvoiceController : Controller
{
    public ActionResult InvoicePdf(int id)
    {
        var model = GetInvoice(id);
        return new ViewAsPdf("Invoice", model);  // Tied to MVC Views
    }
}

// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integration
Imports System.Web.Mvc

Public Class InvoiceController
    Inherits Controller

    Public Function InvoicePdf(id As Integer) As ActionResult
        Dim model = GetInvoice(id)
        Return New ViewAsPdf("Invoice", model) ' Tied to MVC Views
    End Function
End Class

' Problems:
' - No Razor Pages support
' - No Blazor support
' - No minimal APIs support
' - No ASP.NET Core native integration
$vbLabelText   $csharpLabel

IronPDF는 보기 렌더링을 PDF 생성과 분리하여 실제로 더 유연합니다. MVC 뷰뿐만 아니라 모든 HTML을 렌더링할 수 있습니다.


비동기 패턴 마이그레이션

Rotativa는 스레드를 차단합니다; IronPDF는 전체 비동기/await를 지원합니다:

// ❌Rotativa- Blocks the thread
public ActionResult GeneratePdf()
{
    return new ViewAsPdf("Report");
    // This blocks the request thread until PDF is complete
    // Poor scalability under load
}

// ✅IronPDF- 완전 비동기 support
public async Task<IActionResult> GeneratePdf()
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
    // Non-blocking, better scalability
}
// ❌Rotativa- Blocks the thread
public ActionResult GeneratePdf()
{
    return new ViewAsPdf("Report");
    // This blocks the request thread until PDF is complete
    // Poor scalability under load
}

// ✅IronPDF- 완전 비동기 support
public async Task<IActionResult> GeneratePdf()
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
    // Non-blocking, better scalability
}
' ❌Rotativa- Blocks the thread
Public Function GeneratePdf() As ActionResult
    Return New ViewAsPdf("Report")
    ' This blocks the request thread until PDF is complete
    ' Poor scalability under load
End Function

' ✅IronPDF- 완전 비동기 support
Public Async Function GeneratePdf() As Task(Of IActionResult)
    Dim renderer As New ChromePdfRenderer()
    Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
    Return File(pdf.BinaryData, "application/pdf")
    ' Non-blocking, better scalability
End Function
$vbLabelText   $csharpLabel

이동 후 새로운 기능

IronPDF로 마이그레이션한 후에는 Rotativa가 제공할 수 없는 기능을 얻게 됩니다:

PDF 병합

var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");
Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("complete.pdf")
$vbLabelText   $csharpLabel

디지털 서명

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)
$vbLabelText   $csharpLabel

비밀번호 보호

pdf.SecuritySettings.UserPassword = "secret";
pdf.SecuritySettings.UserPassword = "secret";
pdf.SecuritySettings.UserPassword = "secret"
$vbLabelText   $csharpLabel

워터마크

pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

PDF/A 기록 보관 규정 준수

pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
$vbLabelText   $csharpLabel

최신 CSS 지원

// This now works (broke in Rotativa)
var html = @"
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>
    <div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
        <div>Col 1</div><div>Col 2</div><div>Col 3</div>
    </div>";
var pdf = renderer.RenderHtmlAsPdf(html);  // Works!
// This now works (broke in Rotativa)
var html = @"
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>
    <div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
        <div>Col 1</div><div>Col 2</div><div>Col 3</div>
    </div>";
var pdf = renderer.RenderHtmlAsPdf(html);  // Works!
' This now works (broke in Rotativa)
Dim html As String = "
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>
    <div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
        <div>Col 1</div><div>Col 2</div><div>Col 3</div>
    </div>"
Dim pdf = renderer.RenderHtmlAsPdf(html)  ' Works!
$vbLabelText   $csharpLabel

마이그레이션 체크리스트

사전 마이그레이션

  • 코드베이스에서 모든Rotativa사용을 식별
  • RenderingOptions로의 변환에 사용된 CustomSwitches 문서화
  • 변환을 위한 헤더/푸터 플레이스홀더 문법 주의 ([page]{page})
  • ironpdf.com에서IronPDF라이선스 키 획득

패키지 변경 사항

  • RotativaRotativa.AspNetCore NuGet 패키지 제거
  • wkhtmltopdf 바이너리 삭제 (wkhtmltopdf.exe, wkhtmltox.dll)
  • IronPdf NuGet Install-Package

코드 변경 사항

  • 네임스페이스 가져오기 업데이트 (using Rotativa;using IronPdf;)
  • ViewAsPdfChromePdfRenderer + RenderHtmlAsPdf()로 대체
  • UrlAsPdf을(를) RenderUrlAsPdf()(으)로 대체
  • CustomSwitchesRenderingOptions 속성으로 변환
  • 플레이스홀더 문법 업데이트 ([page]{page}, [topage]{total-pages})
  • 개별 MarginRightPageMargins 대체
  • 적절한 곳에서 비동기 패턴으로 변경
  • 애플리케이션 시작 시 라이선스 초기화 추가

마이그레이션 이후

  • 모든 PDF 생성이 올바르게 작동하는지 확인
  • PDF 출력 품질 비교 (Chromium은 더 정확하게 렌더링합니다)
  • CSS 렌더링 개선 사항 확인 (Flexbox/Grid가 이제 작동합니다)
  • JavaScript 실행 테스트 (이제 Chromium으로 신뢰할 수 있음)
  • 보안 스캔 통과 확인(CVE-2022-35583 플래그 없음)
  • wkhtmltopdf 설치 제거를 위해 Docker 구성 업데이트

커티스 차우
기술 문서 작성자

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

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

아이언 서포트 팀

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