IRONSOFTWAREHOME
视频

如何使用C#将RTF转换为PDF

Curtis Chau
Curtis Chau
Updated: 2026年7月19日

为什么要从 NReco PDF 生成器迁移到 IronPDF?

NReco PDF 生成器的关键安全问题

NReco PDF Generator 包装了 wkhtmltopdf 二进制文件,继承了其已知的安全漏洞。 wkhtmltopdf 项目的最后一个稳定版本是 0.12.6 (2020年6月),其上游仓库于 2023年1月2日归档,因此不会有任何补丁发布:

  • CVE-2020-21365: 目录遍历/ Crafted HTML 的本地文件读取 (同源策略弱点)
  • CVE-2022-35583: 通过在 0.12.6 中注入的<iframe>进行服务器端请求伪造 (SSRF) (CVSS 9.8)

NReco PDF 生成器的其他限制

  1. 大规模许可摩擦: 对于非SaaS的单服务器生产部署免费; SaaS、多服务器或再分发场景需要从nrecosite.com购买199美元的企业源代码包。

  2. 弃用的渲染引擎: WebKit Qt (约2012年) 仅支持有限的CSS3/JS:

    • 无 CSS 网格或 Flexbox
    • 无现代 JavaScript(ES6+)
    • 网页字体支持不佳
    • 无 CSS 变量或自定义属性
  3. 外部二进制依赖: 需要根据平台管理 wkhtmltopdf 二进制文件 (wkhtmltopdf.exe, wkhtmltox.dll)。

  4. 维护停滞: NReco.PdfGenerator 1.2.1 于2023年1月8日发布,自此后在nuget.org上未再有任何发布; 底层 wkhtmltopdf 引擎不再更新。

5.**异步支持有限:**同步 API 会阻塞 Web 应用程序中的线程。

NReco PDF 生成器与IronPDF的比较

方面NReco PDF 生成器IronPDF
渲染引擎WebKit Qt (2012)Chromium (当前)
安全性多个未修补的 CVEs (例如 CVE-2020-21365, CVE-2022-35583); 引擎于2023年1月2日归档主动安全更新
CSS 支持CSS2.1, 有限 CSS3完全 CSS3、网格、Flexbox
JavaScript基本 ES5完整的 ES6+、async/await
依赖关系外部 wkhtmltopdf 二进制文件自成一体
异步支持仅同步完整的Async/Await
网络字体有限的完整的谷歌字体,@font-face
许可非SaaS单服务器免费; SaaS/多服务器199美元企业包透明的商业定价
免费级别非SaaS单服务器许可证下免费试用不需要水印

开始之前

前提条件

  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 NReco.PdfGenerator
dotnet remove package NReco.PdfGenerator

# Install IronPDF
dotnet add package IronPdf
SHELL

同时从您的部署中删除 wkhtmltopdf 二进制文件

  • 从项目中删除 wkhtmltopdf.exe, wkhtmltox.dll
  • 删除任何 wkhtmltopdf 安装脚本
  • 删除特定平台的二进制文件夹

许可配置

// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

确定 NReco PDF 生成器的用途

# Find all NReco.PdfGenerator references
grep -r "NReco.PdfGenerator\|HtmlToPdfConverter\|GeneratePdf" --include="*.cs" .
SHELL

完整的 API 参考

核心类映射

NReco PDF 生成器IronPDF
HtmlToPdfConverterChromePdfRenderer
PageMargins个别边距属性
PageOrientationPdfPaperOrientation
PageSizePdfPaperSize

渲染方法映射

NReco PDF 生成器IronPDF
GeneratePdf(html)RenderHtmlAsPdf(html)
GeneratePdfFromFile(url, output)RenderUrlAsPdf(url)
GeneratePdfFromFile(htmlPath, output)RenderHtmlFileAsPdf(path)
(不支持异步)RenderHtmlAsPdfAsync(html)
(不支持异步)RenderUrlAsPdfAsync(url)

页面配置映射

NReco PDF 生成器IronPDF
PageWidth = 210RenderingOptions.PaperSize = PdfPaperSize.A4
PageHeight = 297RenderingOptions.SetCustomPaperSizeinMilimeters(w, h)
Orientation = PageOrientation.LandscapeRenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
Size = PageSize.A4RenderingOptions.PaperSize = PdfPaperSize.A4

边距映射

NReco PDF 生成器IronPDF
Margins.Top = 10RenderingOptions.MarginTop = 10
Margins.Bottom = 10RenderingOptions.MarginBottom = 10
Margins.Left = 10RenderingOptions.MarginLeft = 10
Margins.Right = 10RenderingOptions.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 pdfBytesreturn pdf.BinaryData
new MemoryStream(pdfBytes)new MemoryStream(pdf.BinaryData)

代码迁移示例

示例 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);
    }
}

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");
    }
}

基本区别在于返回类型和保存模式。NReco PDF 生成器的File.WriteAllBytes()手动将其写入磁盘。IronPDF的PdfDocument对象。

这种面向对象的方法还有其他好处:您可以在保存之前对 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);
    }
}

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");
    }
}

NReco PDF Generator 使用数值维度 (PageWidth = 210, PageHeight = 297) 和一个PageMargins对象。IronPDF使用PdfPaperSize枚举(包括标准尺寸如 A4、Letter、Legal)和RenderingOptions对象上的单独边距属性。

关键的迁移变化:

  • PageHeightRenderingOptions.PaperSize = PdfPaperSize.A4
  • new 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);
    }
}

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");
    }
}

NReco PDF Generator 使用令人困惑的GeneratePdfFromFile()方法来处理本地文件和 URL,第二个参数是可为空的。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 生成器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 直接返回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 生成器通常每次调用都会创建一个新的转换器。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;
}

异步支持(新功能)

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;
}

故障排除

问题 1:HtmlToPdfConverter 未找到

**问题:**IronPDF中不存在HtmlToPdfConverter类。

解决方案: 使用ChromePdfRenderer

// NReco PDF Generator
var converter = new HtmlToPdfConverter();

// IronPDF
var renderer = new ChromePdfRenderer();

问题 2:GeneratePdf 返回错误类型

问题: 代码期望PdfDocument

解决方案: 访问.BinaryData属性:

// NReco PDF Generator
byte[] pdfBytes = converter.GeneratePdf(html);

// IronPDF
byte[] pdfBytes = 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;

问题 4:页码未显示

问题: [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.PdfGenerator的使用情况
  • 记录所有CustomWkHtmlPageArgs值 列出所有带有占位符的页眉/页脚HTML模板
  • 确定异步需求(Web 控制器、服务)
  • 检查缩放和边距设置
  • 备份现有 PDF 输出以进行比较
  • 获取IronPDF许可证密钥

软件包变更

  • 移除NReco.PdfGenerator NuGet 包
  • 安装IronPdf NuGet 包: dotnet add package IronPdf
  • 将命名空间导入从using IronPdf;

代码更改

  • 在启动时添加许可证密钥配置
  • HtmlToPdfConverter
  • GeneratePdf(html)
  • GeneratePdfFromFile(url, null)
  • PageMargins对象转换为单独的边距属性
  • 将缩放值从浮点数更新为百分比
  • 更新占位符语法:[page]{page}, [topage]{total-pages}
  • File.WriteAllBytes()
  • 在有利的情况下,将同步调用转换为异步调用。

后迁移

  • 从项目/部署中移除 wkhtmltopdf 二进制文件
  • 更新 Docker 文件以移除 wkhtmltopdf 安装
  • 运行回归测试,比较 PDF 输出
  • 验证页眉/页脚占位符是否正确渲染。
  • 在所有目标平台(Windows、Linux、macOS)上进行测试
  • 更新 CI/CD 流水线,移除 wkhtmltopdf 步骤
  • 更新安全扫描以确认 CVE 已移除

请注意: NReco和wkhtmltopdf是其各自所有者的注册商标。 此网站与NReco或wkhtmltopdf无隶属关系、授权或赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。
Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户