如何在 C# 中從 NReco PDF 生成器轉換到 IronPDF
為何要從NReco PDF 生成器移轉至 IronPDF?
NReco PDF 生成器的關鍵安全問題
NReco PDF Generator 包覆了已廢棄的 wkhtmltopdf 二進位檔,繼承了其所有的安全漏洞。 這並非理論上的問題,自 wkhtmltopdf 於 2020 年被棄用後,已有 20 多個記錄在案的 CVE,但卻沒有可用的修補程式:
- CVE-2020-21365:伺服器端請求偽造 (SSRF)
- CVE-2022-35583:透過 HTML 注入讀取本機文件
- CVE-2022-35580:遠端程式碼執行漏洞
這些漏洞無法修補,因為底層的 wkhtmltopdf 專案已不再維護。
額外的 NReco PDF 生成器限制
1.有浮水印的免費版本:生產用途需要付費許可證,定價不透明,需要聯絡銷售人員。
2.已棄用的渲染引擎: WebKit Qt(大約在 2012 年)提供的現代 Web 支援有限:
- 無 CSS Grid 或 Flexbox
- 不使用現代JavaScript(ES6+)
- 網頁字型支援不佳
- 無 CSS 變數或自訂屬性
3.外部二進位依賴:需要管理每個平台的 wkhtmltopdf 二進位(wkhtmltopdf.exe,wkhtmltox.dll)。
4.無主動開發:封裝器得到維護,但底層引擎沒有更新。
5.非同步支援有限:同步 API 會阻塞 Web 應用程式中的執行緒。
NReco PDF 生成器與IronPDF的比較
| 範疇 | NReco PDF 生成器 | IronPDF |
|---|---|---|
| 渲染引擎 | WebKit Qt (2012) | Chromium (目前) |
| 安全性 | 20 多個 CVE,沒有修補程式 | 主動安全更新 |
| CSS 支援 | CSS2.1, 有限的 CSS3 | 完整的 CSS3、網格、Flexbox |
| JavaScript | 基本 ES5 | 完整的 ES6+、async/await |
| 依賴 | 外部 wkhtmltopdf 二進位 | 自成一格 |
| 同步支援 | 僅同步 | 完整的 async/await |
| 網頁字型 | 限額 | 完整的 Google 字型,@font-face |
| 授權 | 價格不透明,請聯絡銷售人員 | 透明的定價 |
| 免費試用 | 水印 | 完整功能 |
對於計劃在 2025 年和 2026 年之前採用 .NET 10 和 C# 14 的團隊而言,IronPDF 提供了一個面向未來的基礎,具有積極的開發和現代化的渲染能力。
開始之前
先決條件
- .NET環境: .NET Framework 4.6.2+ 或.NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet存取權限:能夠安裝NuGet套件
- IronPDF許可證:請從IronPDF取得您的許可證密鑰。
NuGet 套件變更
# Remove NReco.PdfGenerator
dotnet remove package NReco.PdfGenerator
# Install IronPDF
dotnet add package IronPdf
# Remove NReco.PdfGenerator
dotnet remove package NReco.PdfGenerator
# Install IronPDF
dotnet add package IronPdf
同時從您的部署中移除 wkhtmltopdf 二進位檔案:
- 從項目中刪除
wkhtmltopdf.exe和wkhtmltox.dll - 移除任何 wkhtmltopdf 安裝腳本
- 刪除特定平台的二進位資料夾
授權組態
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
識別 NReco PDF 生成器用法
# Find all NReco.PdfGenerator references
grep -r "NReco.PdfGenerator\|HtmlToPdfConverter\|GeneratePdf" --include="*.cs" .
# Find all NReco.PdfGenerator references
grep -r "NReco.PdfGenerator\|HtmlToPdfConverter\|GeneratePdf" --include="*.cs" .
完整的 API 參考資料
核心類對應
| NReco PDF 生成器 | IronPDF |
|---|---|
HtmlToPdfConverter |
ChromePdfRenderer |
PageMargins |
個別邊界屬性 |
PageOrientation |
PdfPaperOrientation |
PageSize |
PdfPaperSize |
渲染方法映射
| NReco PDF 生成器 | IronPDF |
|---|---|
GeneratePdf(html) |
RenderHtmlAsPdf(html) |
GeneratePdfFromFile(url, output) |
RenderUrlAsPdf(url) |
GeneratePdfFromFile(htmlPath, output) |
RenderHtmlFileAsPdf(path) |
| (不支援 async) | RenderHtmlAsPdfAsync(html) |
| (不支援 async) | RenderUrlAsPdfAsync(url) |
頁面組態對應
| NReco PDF 生成器 | IronPDF |
|---|---|
PageWidth = 210 |
RenderingOptions.PaperSize = PdfPaperSize.A4 |
PageHeight = 297 |
RenderingOptions.SetCustomPaperSizeinMilimeters(w, h) |
Orientation = PageOrientation.Landscape |
RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape |
Size = PageSize.A4 |
RenderingOptions.PaperSize = PdfPaperSize.A4 |
邊界對應
| NReco PDF 生成器 | IronPDF |
|---|---|
Margins.Top = 10 |
RenderingOptions.MarginTop = 10 |
Margins.Bottom = 10 |
RenderingOptions.MarginBottom = 10 |
Margins.Left = 10 |
RenderingOptions.MarginLeft = 10 |
Margins.Right = 10 |
RenderingOptions.MarginRight = 10 |
new PageMargins { ... } |
個別屬性 |
頁首/頁尾占位符對應
| NReco PDF 生成器 (wkhtmltopdf) | IronPDF |
|---|---|
[page] |
{page} |
[topage] |
{total-pages} |
[date] |
{date} |
[time] |
{time} |
[title] |
{html-title} |
輸出處理映射
| NReco PDF 生成器 | IronPDF |
|---|---|
byte[] pdfBytes = GeneratePdf(html) |
PdfDocument pdf = RenderHtmlAsPdf(html) |
File.WriteAllBytes(path, bytes) |
pdf.SaveAs(path) |
return pdfBytes |
return pdf.BinaryData |
new MemoryStream(pdfBytes) |
pdf.Stream |
程式碼遷移範例
範例 1:基本 HTML 到 PDF
之前 (NReco PDF 生成器):
// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;
class Program
{
static void Main()
{
var htmlToPdf = new HtmlToPdfConverter();
var htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
var pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
File.WriteAllBytes("output.pdf", pdfBytes);
}
}
// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;
class Program
{
static void Main()
{
var htmlToPdf = new HtmlToPdfConverter();
var htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
var pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
File.WriteAllBytes("output.pdf", pdfBytes);
}
}
Imports NReco.PdfGenerator
Imports System.IO
Class Program
Shared Sub Main()
Dim htmlToPdf = New HtmlToPdfConverter()
Dim htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>"
Dim pdfBytes = htmlToPdf.GeneratePdf(htmlContent)
File.WriteAllBytes("output.pdf", pdfBytes)
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System.IO;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System.IO;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Imports System.IO
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim htmlContent = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
End Sub
End Class
基本差異在於回傳類型和儲存模式。NReco PDF 生成器的 HtmlToPdfConverter.GeneratePdf() 傳回一個 byte[],您必須使用 File.WriteAllBytes() 手動將其寫入磁碟。IronPDF的 ChromePdfRenderer.RenderHtmlAsPdf() 傳回一個 PdfDocument 對象,該物件具有內建的 SaveAs() 方法。
這種物件導向的方法提供了額外的好處:您可以在儲存之前對 PDF 進行操作(新增水印、合併文件、新增安全性)。 如果您需要原始位元組以與現有程式碼相容,請使用 pdf.BinaryData。 請參閱 HTML to PDF 文件,以瞭解其他渲染選項。
範例 2:自訂頁面大小與頁邊空白
之前 (NReco PDF 生成器):
// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;
class Program
{
static void Main()
{
var htmlToPdf = new HtmlToPdfConverter();
htmlToPdf.PageWidth = 210;
htmlToPdf.PageHeight = 297;
htmlToPdf.Margins = new PageMargins { Top = 10, Bottom = 10, Left = 10, Right = 10 };
var htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>";
var pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
File.WriteAllBytes("custom-size.pdf", pdfBytes);
}
}
// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;
class Program
{
static void Main()
{
var htmlToPdf = new HtmlToPdfConverter();
htmlToPdf.PageWidth = 210;
htmlToPdf.PageHeight = 297;
htmlToPdf.Margins = new PageMargins { Top = 10, Bottom = 10, Left = 10, Right = 10 };
var htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>";
var pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
File.WriteAllBytes("custom-size.pdf", pdfBytes);
}
}
Imports NReco.PdfGenerator
Imports System.IO
Class Program
Shared Sub Main()
Dim htmlToPdf = New HtmlToPdfConverter()
htmlToPdf.PageWidth = 210
htmlToPdf.PageHeight = 297
htmlToPdf.Margins = New PageMargins With {.Top = 10, .Bottom = 10, .Left = 10, .Right = 10}
Dim htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>"
Dim pdfBytes = htmlToPdf.GeneratePdf(htmlContent)
File.WriteAllBytes("custom-size.pdf", pdfBytes)
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
var htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("custom-size.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
var htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("custom-size.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 10
renderer.RenderingOptions.MarginBottom = 10
renderer.RenderingOptions.MarginLeft = 10
renderer.RenderingOptions.MarginRight = 10
Dim htmlContent = "<html><body><h1>Custom Page Size</h1><p>A4 size document with margins.</p></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("custom-size.pdf")
End Sub
End Class
NReco PDF 產生器使用數值維度(PageWidth = 210,PageHeight = 297)和 PageMargins 物件。IronPDF使用 PdfPaperSize 枚舉(包括 A4、Letter、Legal 等標準尺寸)和 RenderingOptions 物件上的各個邊距屬性。
主要的轉移變化:
PageWidth/PageHeight→RenderingOptions.PaperSize = PdfPaperSize.A4new PageMargins { Top = 10, ... }→ Individual properties:RenderingOptions.MarginTop = 10
對於枚舉未涵蓋的自訂紙張尺寸,請使用 RenderingOptions.SetCustomPaperSizeinMilimeters(width, height)。 進一步瞭解 頁面配置選項。
範例 3:URL 到 PDF 的轉換
之前 (NReco PDF 生成器):
// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;
class Program
{
static void Main()
{
var htmlToPdf = new HtmlToPdfConverter();
var pdfBytes = htmlToPdf.GeneratePdfFromFile("https://www.example.com", null);
File.WriteAllBytes("webpage.pdf", pdfBytes);
}
}
// NuGet: Install-Package NReco.PdfGenerator
using NReco.PdfGenerator;
using System.IO;
class Program
{
static void Main()
{
var htmlToPdf = new HtmlToPdfConverter();
var pdfBytes = htmlToPdf.GeneratePdfFromFile("https://www.example.com", null);
File.WriteAllBytes("webpage.pdf", pdfBytes);
}
}
Imports NReco.PdfGenerator
Imports System.IO
Class Program
Shared Sub Main()
Dim htmlToPdf As New HtmlToPdfConverter()
Dim pdfBytes As Byte() = htmlToPdf.GeneratePdfFromFile("https://www.example.com", Nothing)
File.WriteAllBytes("webpage.pdf", pdfBytes)
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.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://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
NReco PDF Generator 對本機檔案和 URL 都使用了名稱令人困惑的 GeneratePdfFromFile() 方法,並且第二個參數可以為空。IronPDF提供專用方法:RenderUrlAsPdf() 用於 URL,RenderHtmlFileAsPdf() 用於本機 HTML 檔案。
IronPDF 的方法更簡潔、更直覺。對於非同步 Web 應用程序,請使用 await renderer.RenderUrlAsPdfAsync(url) 來避免阻塞線程——這是NReco PDF 生成器無法做到的。
關鍵遷移注意事項
縮放值轉換
NReco PDF Generator 使用浮動值 (0.0-2.0),而IronPDF則使用百分比整數:
// NReco PDF Generator: Zoom = 0.9f (90%)
// IronPDF: Zoom = 90
// Conversion formula:
int ironPdfZoom = (int)(nrecoZoom * 100);
// NReco PDF Generator: Zoom = 0.9f (90%)
// IronPDF: Zoom = 90
// Conversion formula:
int ironPdfZoom = (int)(nrecoZoom * 100);
' NReco PDF Generator: Zoom = 0.9F (90%)
' IronPDF: Zoom = 90
' Conversion formula:
Dim ironPdfZoom As Integer = CInt(nrecoZoom * 100)
占位符語法更新
所有頁首/頁尾的占位符都必須更新:
| NReco PDF 生成器 | IronPDF |
|---|---|
[page] |
{page} |
[topage] |
{total-pages} |
[date] |
{date} |
[title] |
{html-title} |
// NReco PDF Generator:
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>";
// IronPDF:
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div>Page {page} of {total-pages}</div>",
MaxHeight = 20
};
// NReco PDF Generator:
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>";
// IronPDF:
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div>Page {page} of {total-pages}</div>",
MaxHeight = 20
};
Imports NReco.PdfGenerator
Imports IronPdf
' NReco PDF Generator:
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>"
' IronPDF:
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.HtmlFragment = "<div>Page {page} of {total-pages}</div>",
.MaxHeight = 20
}
返回類型變更
NReco PDF Generator 直接回傳 byte[];IronPDF返回 PdfDocument:
//NReco PDF 生成器pattern:
byte[] pdfBytes = converter.GeneratePdf(html);
File.WriteAllBytes("output.pdf", pdfBytes);
//IronPDFpattern:
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Or if you need bytes:
byte[] pdfBytes = renderer.RenderHtmlAsPdf(html).BinaryData;
//NReco PDF 生成器pattern:
byte[] pdfBytes = converter.GeneratePdf(html);
File.WriteAllBytes("output.pdf", pdfBytes);
//IronPDFpattern:
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Or if you need bytes:
byte[] pdfBytes = renderer.RenderHtmlAsPdf(html).BinaryData;
Imports System.IO
' NReco PDF 生成器pattern:
Dim pdfBytes As Byte() = converter.GeneratePdf(html)
File.WriteAllBytes("output.pdf", pdfBytes)
' IronPDFpattern:
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' Or if you need bytes:
Dim pdfBytes As Byte() = renderer.RenderHtmlAsPdf(html).BinaryData
線程安全與重複性
NReco PDF Generator 通常會在每次呼叫時建立新的轉換器。IronPDF的 ChromePdfRenderer 是線程安全的,可以重複使用:
//NReco PDF 生成器pattern (creates new each time):
public byte[] Generate(string html)
{
var converter = new HtmlToPdfConverter();
return converter.GeneratePdf(html);
}
//IronPDFpattern (reuse renderer, thread-safe):
private readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();
public byte[] Generate(string html)
{
return _renderer.RenderHtmlAsPdf(html).BinaryData;
}
//NReco PDF 生成器pattern (creates new each time):
public byte[] Generate(string html)
{
var converter = new HtmlToPdfConverter();
return converter.GeneratePdf(html);
}
//IronPDFpattern (reuse renderer, thread-safe):
private readonly ChromePdfRenderer _renderer = new ChromePdfRenderer();
public byte[] Generate(string html)
{
return _renderer.RenderHtmlAsPdf(html).BinaryData;
}
Imports NReco.PdfGenerator
Imports IronPdf
' NReco PDF 生成器pattern (creates new each time):
Public Function Generate(html As String) As Byte()
Dim converter As New HtmlToPdfConverter()
Return converter.GeneratePdf(html)
End Function
' IronPDFpattern (reuse renderer, thread-safe):
Private ReadOnly _renderer As New ChromePdfRenderer()
Public Function Generate(html As String) As Byte()
Return _renderer.RenderHtmlAsPdf(html).BinaryData
End Function
同步支援(新功能)
IronPDF 支援NReco PDF 生成器無法提供的 async/await 模式:
// NReco PDF Generator: No async support available
// IronPDF: Full async support
public async Task<byte[]> GenerateAsync(string html)
{
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
// NReco PDF Generator: No async support available
// IronPDF: Full async support
public async Task<byte[]> GenerateAsync(string html)
{
var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
Imports System.Threading.Tasks
' NReco PDF Generator: No async support available
' IronPDF: Full async support
Public Async Function GenerateAsync(html As String) As Task(Of Byte())
Dim pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Function
疑難排解
問題 1:HtmlToPdfConverter 未找到
問題:IronPDF中不存在 HtmlToPdfConverter 類別。
解:使用 ChromePdfRenderer:
// NReco PDF Generator
var converter = new HtmlToPdfConverter();
// IronPDF
var renderer = new ChromePdfRenderer();
// NReco PDF Generator
var converter = new HtmlToPdfConverter();
// IronPDF
var renderer = new ChromePdfRenderer();
' NReco PDF Generator
Dim converter As New HtmlToPdfConverter()
' IronPDF
Dim renderer As New ChromePdfRenderer()
問題 2:GeneratePdf 返回錯誤的類型
問題:代碼期望 byte[],但得到 PdfDocument。
解決方案:存取 .BinaryData 屬性:
// NReco PDF Generator
byte[] pdfBytes = converter.GeneratePdf(html);
// IronPDF
byte[] pdfBytes = renderer.RenderHtmlAsPdf(html).BinaryData;
// NReco PDF Generator
byte[] pdfBytes = converter.GeneratePdf(html);
// IronPDF
byte[] pdfBytes = renderer.RenderHtmlAsPdf(html).BinaryData;
' NReco PDF Generator
Dim pdfBytes As Byte() = converter.GeneratePdf(html)
' IronPDF
Dim pdfBytes As Byte() = renderer.RenderHtmlAsPdf(html).BinaryData
問題 3:未找到 PageMargins 物件
問題:IronPDF中不存在 PageMargins 類別。
解決方法:使用單獨的邊距屬性:
// NReco PDF Generator
converter.Margins = new PageMargins { Top = 10, Bottom = 10, Left = 10, Right = 10 };
// IronPDF
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
// NReco PDF Generator
converter.Margins = new PageMargins { Top = 10, Bottom = 10, Left = 10, Right = 10 };
// IronPDF
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
' NReco PDF Generator
converter.Margins = New PageMargins With {.Top = 10, .Bottom = 10, .Left = 10, .Right = 10}
' IronPDF
renderer.RenderingOptions.MarginTop = 10
renderer.RenderingOptions.MarginBottom = 10
renderer.RenderingOptions.MarginLeft = 10
renderer.RenderingOptions.MarginRight = 10
問題 4:未顯示頁碼
問題: [page] 和 [topage] 佔位符不起作用。
解決方案:更新IronPDF佔位符語法:
// NReco PDF Generator
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>";
// IronPDF
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div>Page {page} of {total-pages}</div>",
MaxHeight = 20
};
// NReco PDF Generator
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>";
// IronPDF
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div>Page {page} of {total-pages}</div>",
MaxHeight = 20
};
Imports NReco.PdfGenerator
Imports IronPdf
converter.PageFooterHtml = "<div>Page [page] of [topage]</div>"
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.HtmlFragment = "<div>Page {page} of {total-pages}</div>",
.MaxHeight = 20
}
遷移清單
預遷移
- 清點程式碼庫中所有
NReco.PdfGenerator的使用情況 - 記錄所有
CustomWkHtmlArgs和CustomWkHtmlPageArgs值 列出所有有佔位符的頁首/頁尾HTML模板 - 確定非同步需求(Web 控制器、服務)
- 檢查縮放和邊距設置
- 備份現有 PDF 輸出以進行比較
- 取得IronPDF許可證密鑰
套件變更
- 刪除
NReco.PdfGeneratorNuGet 套件 安裝IronPdfNuGet 套件:dotnet add package IronPdf - 將命名空間匯入從
using NReco.PdfGenerator;更新為using IronPdf;
程式碼變更
- 在啟動時新增許可證金鑰配置
- 將
HtmlToPdfConverter替換為ChromePdfRenderer - 將
GeneratePdf(html)替換為RenderHtmlAsPdf(html) - 將
GeneratePdfFromFile(url, null)替換為RenderUrlAsPdf(url)將PageMargins物件轉換為單獨的邊距屬性 - 將縮放值從浮點數更新為百分比
- 更新佔位語法:
[page]→{page},[topage]→{total-pages} - 將
File.WriteAllBytes()替換為pdf.SaveAs() - 在有利的情況下,將同步呼叫轉換為非同步呼叫。
後遷移
- 從專案/部署移除 wkhtmltopdf 二進位文件
- 更新 Docker 檔案以移除 wkhtmltopdf 安裝
- 執行迴歸測試,比較 PDF 輸出
- 驗證頁首/頁尾佔位符是否正確渲染。
- 在所有目標平台(Windows、Linux、macOS)上進行測試
- 更新 CI/CD 管線,移除 wkhtmltopdf 步驟
- 更新安全掃描以確認 CVE 已移除

