跳至頁尾內容
影片

如何在 .NET Maui 中查看 PDF 文件

從Rotativa遷移到IronPDF,可以解決關鍵的安全漏洞,同時讓您的PDF生成工作流程現代化。 本指南提供了一個完整的逐步遷移路徑,消除了已終止的wkhtmltopdf依賴,支持現代CSS和JavaScript,並提供跨平台的相容性,不僅限於ASP.NET MVC。

為什麼從Rotativa遷移到IronPDF

瞭解Rotativa

Rotativa長期以來一直是開發人員在C#中生成PDF的流行選擇。 它利用wkhtmltopdf工具將HTML內容轉換為PDF格式。 Rotativa是一個開源程式庫,專為ASP.NET MVC應用程式設計。 然而,儘管吸引了大量觀眾,但Rotativa對過時技術堆棧的依賴,帶來了不一定立即顯而易見的挑戰。

Rotativa的核心是提供了一種簡單的方法將PDF生成整合到ASP.NET MVC專案中,利用wkhtmltopdf作為其後端功能。

關鍵安全公告

Rotativa包裹了wkhtmltopdf,其中存在關鍵未修補的安全漏洞。

屬性
CVE ID CVE-2022-35583
嚴重性 關鍵 (9.8/10)
攻擊向量 網路
狀態 無修補版本(wkhtmltopdf執行檔已存檔)
受影響 所有捆綁wkhtmltopdf 0.12.6的Rotativa版本

wkhtmltopdf GitHub儲存庫於2023年1月2日被存檔(僅讀)。維護者的狀態頁面指出該專案依賴於Qt 4(自2015年以來未受支持)和2012年的WebKit分支,並明確警告不要使用不受信任的HTML。 CVE-2022-35583沒有修補版本,因此任何使用Rotativa的應用程式都會暴露在風險中,除非HTML輸入被完全淨化。

攻擊如何運作


<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 現代 Chromium
CSS3 部分 支援
Flexbox/Grid 不支持 支援
JavaScript 不可靠 完整ES6+
Razor Pages 不支持 支援
Blazor 不支持 支援
PDF 操作 不可用 全面
數位簽名 不可用 全面
PDF/A合規性 不可用 全面
Async/Await 只有同步 全面支持異步
開源 是,MIT授權 否,商業授權

對於針對當前 .NET 版本的團隊,IronPDF 提供了現代化的 Chromium 渲染和跨平台支持,這是Rotativa無法提供的。


開始之前

前提條件

  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包變更

原始的Rotativa封裝目標是典型的ASP.NET MVC 5(最後發布 v1.7.3, 2017-09-29)。 社區分叉Rotativa.AspNetCore(webgio)於2024年11月6日達到v1.4.0,支持 .NET Core 3.1到 .NET 8,但這兩個封裝仍然捆綁wkhtmltopdf 0.12.6 執行檔(最後一次上游發行2020年6月)。

# 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.AspNetCore
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.AspNetCore
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可以隨處運行:控制台應用程式、Web API、Blazor、Razor Pages或任何.NET專案型別。 您可以呼叫RenderHtmlAsPdf(),並使用HTML字串並儲存結果。 無需MVC控制器,不依賴於視圖。 查看更多HTML到PDF文件以獲得完整的範例。

範例2:URL轉PDF轉換

之前(Rotativa):

// NuGet: Install-Package Rotativa.AspNetCore
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.AspNetCore
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的ActionResult。 IronPDF的PdfDocument物件。 URL渲染使用現代Chromium代替wkhtmltopdf的脆弱和過時的WebKit引擎。瞭解更多內容,請參閱我們的教程

範例3:具有頁碼的標頭和頁腳

之前(Rotativa):

// NuGet: Install-Package Rotativa.AspNetCore
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,
                // Margins(top, right, bottom, left)
                PageMargins = new Margins(20, 10, 20, 10),
                CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [topage]\""
            };
        }
    }
}
// NuGet: Install-Package Rotativa.AspNetCore
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,
                // Margins(top, right, bottom, left)
                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,
                ' Margins(top, right, bottom, left)
                .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使用[topage]的頁眉和頁尾配置。 這種基於字串的方法容易出錯且在編譯時難以驗證。

IronPDF使用強型別的DrawDividerLine的屬性。 佔位符語法從{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生成分開,這實際上更具靈活性——您可以渲染任何HTML,而不僅僅是MVC視圖。


異步模式遷移

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的使用情況
  • 文件中文字的CustomSwitches用於轉換為RenderingOptions
  • 記錄頁眉/頁腳佔位符語法以進行轉換([page]{page}
  • 獲取IronPDF授權金鑰來自ironpdf.com

套件變更

  • 刪除Rotativa.AspNetCore NuGet包
  • 刪除wkhtmltopdf二進位檔(wkhtmltopdf.exe, wkhtmltox.dll
  • 安裝IronPdf NuGet包

程式碼變更

  • 更新命名空間導入(using Rotativa;using IronPdf;
  • ChromePdfRenderer + ViewAsPdf
  • UrlAsPdf
  • RenderingOptions屬性
  • 更新佔位符語法([page]{page}, [topage]{total-pages}
  • 用個別的PageMargins
  • 在適當位置更改為異步模式
  • 在應用程式啟動時新增授權初始化

遷移後

  • 驗證所有PDF生成效果正確
  • 比較PDF輸出質量(Chromium渲染更準確)
  • 驗證CSS渲染改進(Flexbox/Grid現在可以運行)
  • 測試JavaScript執行(現在使用Chromium更可靠)
  • 確認安全掃描通過(不再有CVE-2022-35583標誌)
  • 更新Docker配置以刪除wkhtmltopdf安裝

請注意Rotativa和wkhtmltopdf是其各自所有者的註冊商標。 本網站與Rotativa或wkhtmltopdf無關,未被其認可或贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供參考,反映撰寫時公開可用的資訊。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話