IRONSOFTWAREHOME
视频

如何在C#中将PDF光栅化为图像

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

从 jsreport 迁移到IronPDF可将您的 .NET PDF 工作流程从依赖 Node.js 的系统(带有外部二进制管理和单独的服务器进程)转变为完全在进程中运行的纯 .NET 库。 本指南提供了一个全面、循序渐进的迁移路径,为专业的 .NET 开发人员消除了基础架构的复杂性和 JavaScript 模板要求。

为什么要从 jsreport 迁移到 IronPDF?

jsreport 面临的挑战

jsreport 引入了不属于纯 .NET 环境的复杂性:

  1. **Node.js 依赖项:**需要 Node.js 运行时和二进制文件,这给原本应该是一个简单的 .NET 应用程序增加了基础架构的复杂性。

  2. **外部二进制管理:**必须通过独立的NuGet包下载和管理适用于Windows、Linux和OSX的平台特定二进制文件 (jsreport.Binary, jsreport.Binary.Linux, jsreport.Binary.OSX)。

  3. **独立服务器进程:**作为工具或网络服务器运行——需要使用KillAsync()生命周期方法进行额外的进程管理。

  4. **JavaScript 模板:**强制学习 Handlebars、JsRender 或其他 JavaScript 模板系统,而不是使用原生 C# 功能。

  5. **复杂的请求结构:**即使是简单的PDF生成,也需要冗长的Template配置。

  6. **许可证限制:**免费套餐每个实例最多5个模板; 超出这范围的商业用途需要Enterprise许可证($395/年/实例)或Enterprise Scale($1,295/年,无版税适用于所有实例)。 See jsreport.net/buy.

7.**基于流的输出:**返回需要手动文件操作和内存流管理的流。

jsreport 与IronPDF对比

特征jsreportIronPDF
运行时间Node.js + .NET纯 .NET
二进制管理手册(jsreport.二进制包)自动翻译
服务器流程要求(实用程序或网络服务器)翻译中
模板制作JavaScript(手柄等)C# (Razor、字符串插值)
API 风格冗长的请求对象简洁流畅的方法
产出PdfDocument 对象
PDF 操作有限的广泛(合并、拆分、编辑)
异步支持仅异步同步和异步

对于计划采用.NET 10和C# 14的团队,IronPDF提供了一个原生的.NET基础,无需外部运行时依赖。


迁移复杂性评估

按功能估算的工作量

特征迁移复杂性
HTML 至 PDF极低
URL 至 PDF极低
页眉/页脚low
页面设置low
服务器生命周期low
二进制管理low

范式转换

jsreport 迁移的根本转变在于从冗长的请求对象(包含服务器管理)转变为简单的进程内方法调用:

jsreport:  LocalReporting().UseBinary().AsUtility().Create() → RenderAsync(RenderRequest) →流→ File
IronPDF:   ChromePdfRenderer → RenderHtmlAsPdf(html) → SaveAs()
Text

开始之前

前提条件

  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 jsreport packages
dotnet remove package jsreport.Binary
dotnet remove package jsreport.Binary.Linux
dotnet remove package jsreport.Binary.OSX
dotnet remove package jsreport.Local
dotnet remove package jsreport.Types
dotnet remove package jsreport.Client

# Install IronPDF
dotnet add package IronPdf
SHELL

许可配置

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

确定 jsreport 的用法

# Find all jsreport references
grep -r "using jsreport\|LocalReporting\|RenderRequest\|RenderAsync" --include="*.cs" .
grep -r "JsReportBinary\|Template\|Recipe\|Engine\." --include="*.cs" .
SHELL

完整的 API 参考

类映射

jsreport 类IronPDF 同等产品
LocalReportingChromePdfRenderer
ReportingServiceChromePdfRenderer
RenderRequest方法参数
Template方法参数
ChromeRenderingOptions
ReportPdfDocument
Engine(不需要)

方法映射

jsreport 方法IronPDF 同等产品
LocalReporting().UseBinary().AsUtility().Create()new ChromePdfRenderer()
rs.RenderAsync(request)renderer.RenderHtmlAsPdf(html)
rs.StartAsync()(不需要)
rs.KillAsync()(不需要)
report.Content.CopyTo(stream)pdf.SaveAs(path)pdf.BinaryData

渲染请求属性映射

jsreport 模板属性IronPDF 同等产品
Template.ContentRenderHtmlAsPdf() 的第一个参数
Template.Recipe = Recipe.ChromePdf(不需要)
Template.Engine = Engine.None(不需要)
Chrome.HeaderTemplateRenderingOptions.TextHeaderHtmlHeader
Chrome.FooterTemplateRenderingOptions.TextFooterHtmlFooter
Chrome.DisplayHeaderFooter(自动)
Chrome.MarginTopRenderingOptions.MarginTop

占位符映射(页眉/页脚)

jsreport 占位符IronPDF 占位符
<span class='pageNumber'></span>{page}
<span class='totalPages'></span>{total-pages}
{#pageNum}{page}
{#numPages}{total-pages}
{#timestamp}{date}

代码迁移示例

示例 1:将基本 HTML 转换为 PDF.

之前 (jsreport):

// NuGet: Install-Package jsreport.Binary
// NuGet: Install-Package jsreport.Local
// NuGet: Install-Package jsreport.Types
using jsreport.Binary;
using jsreport.Local;
using jsreport.Types;
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var rs = new LocalReporting()
            .UseBinary(JsReportBinary.GetBinary())
            .AsUtility()
            .Create();

        var report = await rs.RenderAsync(new RenderRequest()
        {
            Template = new Template()
            {
                Recipe = Recipe.ChromePdf,
                Engine = Engine.None,
                Content = "<h1>Hello from jsreport</h1><p>This is a PDF document.</p>"
            }
        });

        using (var fileStream = File.Create("output.pdf"))
        {
            report.Content.CopyTo(fileStream);
        }

        Console.WriteLine("PDF created successfully!");
    }
}

After (IronPDF):

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

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello from IronPDF</h1><p>This is a PDF document.</p>");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully!");
    }
}

jsreport方法需要三个NuGet包 (jsreport.Binary, jsreport.Local, jsreport.Types)、三个命名空间导入、仅支持异步执行、一个流畅的builder链 (using块。

IronPDF 将其简化为一个 NuGet 包、一个命名空间、三行代码和同步执行。 PdfDocument。 有关其他渲染选项,请参阅 HTML to PDF 文档

示例 2:URL 转 PDF.

之前 (jsreport):

// NuGet: Install-Package jsreport.Binary
// NuGet: Install-Package jsreport.Local
// NuGet: Install-Package jsreport.Types
using jsreport.Binary;
using jsreport.Local;
using jsreport.Types;
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var rs = new LocalReporting()
            .UseBinary(JsReportBinary.GetBinary())
            .AsUtility()
            .Create();

        var report = await rs.RenderAsync(new RenderRequest()
        {
            Template = new Template()
            {
                Recipe = Recipe.ChromePdf,
                Engine = Engine.None,
                Content = "<html><body><script>window.location='https://example.com';</script></body></html>"
            }
        });

        using (var fileStream = File.Create("webpage.pdf"))
        {
            report.Content.CopyTo(fileStream);
        }

        Console.WriteLine("Webpage PDF created successfully!");
    }
}

After (IronPDF):

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

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("Webpage PDF created successfully!");
    }
}

jsreport可以通过在请求中设置Chrome.Url来渲染URL,但没有顶级便捷方法——现有代码中的常见模式是前面显示的JavaScript重定向变通方法 (window.location='https://example.com'),在阻止脚本导航的网站上可能会失败。

IronPDF提供了一个专门的RenderUrlAsPdf()方法,该方法直接将URL作为参数,支持完整的JavaScript执行和现代CSS。 了解有关 URL 至 PDF 转换的更多信息。

示例 3:带页眉和页脚的 PDF 文件

之前 (jsreport):

// NuGet: Install-Package jsreport.Binary
// NuGet: Install-Package jsreport.Local
// NuGet: Install-Package jsreport.Types
using jsreport.Binary;
using jsreport.Local;
using jsreport.Types;
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var rs = new LocalReporting()
            .UseBinary(JsReportBinary.GetBinary())
            .AsUtility()
            .Create();

        var report = await rs.RenderAsync(new RenderRequest()
        {
            Template = new Template()
            {
                Recipe = Recipe.ChromePdf,
                Engine = Engine.None,
                Content = "<h1>Document with Header and Footer</h1><p>Main content goes here.</p>",
                Chrome = new Chrome()
                {
                    DisplayHeaderFooter = true,
                    HeaderTemplate = "<div style='font-size:10px; text-align:center; width:100%;'>Custom Header</div>",
                    FooterTemplate = "<div style='font-size:10px; text-align:center; width:100%;'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></div>"
                }
            }
        });

        using (var fileStream = File.Create("document_with_headers.pdf"))
        {
            report.Content.CopyTo(fileStream);
        }

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

After (IronPDF):

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

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
        {
            CenterText = "Custom Header",
            FontSize = 10
        };
        renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
        {
            CenterText = "Page {page} of {total-pages}",
            FontSize = 10
        };
        
        var pdf = renderer.RenderHtmlAsPdf("<h1>Document with Header and Footer</h1><p>Main content goes here.</p>");
        pdf.SaveAs("document_with_headers.pdf");
        Console.WriteLine("PDF with headers and footers created successfully!");
    }
}

jsreport方法需要在DisplayHeaderFooter = true,并使用带有特殊CSS类占位符 (<span class='pageNumber'></span>, <span class='totalPages'></span>) 的HTML模板。 页眉和页脚模板必须包含完整的内联样式。

IronPDF提供了一个更简洁的FontSize的属性。 页码占位符使用更简单的{total-pages}语法。 有关 HTML 页眉选项,请参阅 页眉和页脚文档


关键迁移说明

消除服务器生命周期管理

jsreport 需要明确的服务器生命周期管理:

// jsreport (DELETE THIS):
var rs = new LocalReporting()
    .UseBinary(JsReportBinary.GetBinary())
    .AsUtility()
    .Create();

// Or for web server mode:
var rs = new LocalReporting()
    .UseBinary(JsReportBinary.GetBinary())
    .AsWebServer()
    .Create();

await rs.StartAsync();
// ... use rs ...
await rs.KillAsync();

IronPDF 完全在进程中运行--无需启动服务器、无需进程管理、无需清理:

// IronPDF:
var renderer = new ChromePdfRenderer();
// Just use it—no lifecycle management needed

移除特定平台的二进制包

jsreport 需要为每个目标平台分别提供 NuGet 包:

# DELETE these platform-specific packages:
dotnet remove package jsreport.Binary
dotnet remove package jsreport.Binary.Linux
dotnet remove package jsreport.Binary.OSX
SHELL

IronPDF 通过一个 NuGet 包自动处理所有平台要求。

更新占位符语法

jsreport 使用 CSS 类占位符或大括号占位符。IronPDF使用不同的语法:

// jsreport placeholders:
"<span class='pageNumber'></span>"  // or {#pageNum}
"<span class='totalPages'></span>"  // or {#numPages}

//IronPDFplaceholders:
"{page}"
"{total-pages}"
"{date}"
"{html-title}"
C#

用C#字符串插值替换Handlebars

jsreport经常使用Handlebars模板与Engine.Handlebars一起使用:

// jsreport Handlebars (DELETE THIS):
Template = new Template
{
    Content = "<h1>Hello, {{name}}</h1>",
    Engine = Engine.Handlebars
},
Data = new { name = "World" }

//IronPDFwith C# string interpolation:
string name = "World";
string html = $"<h1>Hello, {name}</h1>";
var pdf = renderer.RenderHtmlAsPdf(html);
C#

简化流处理

jsreport 返回一个需要手动复制的流:

// jsreport stream handling (DELETE THIS):
using (var fileStream = File.Create("output.pdf"))
{
    report.Content.CopyTo(fileStream);
}

// Or for byte array:
using (var memoryStream = new MemoryStream())
{
    await report.Content.CopyToAsync(memoryStream);
    return memoryStream.ToArray();
}

//IronPDFdirect access:
pdf.SaveAs("output.pdf");
// Or:
byte[] bytes = pdf.BinaryData;
C#

故障排除

问题 1:未找到本地报告

**问题:**代码引用了在IronPDF中不存在的LocalReporting类。

**解决:**替换为ChromePdfRenderer

// jsreport
var rs = new LocalReporting().UseBinary().AsUtility().Create();

// IronPDF
var renderer = new ChromePdfRenderer();

问题 2:未找到渲染请求

**问题:**代码使用了Template包装对象。

**解决方案:**直接将 HTML 传递给渲染方法:

// jsreport
await rs.RenderAsync(new RenderRequest { Template = new Template { Content = html } });

// IronPDF
var pdf = renderer.RenderHtmlAsPdf(html);

问题 3:页码未显示

**问题:**使用了jsreport占位符语法<span class='pageNumber'></span>

**解决方案:**更新IronPDF占位符语法:

// jsreport syntax (won't work)
"Page <span class='pageNumber'></span> of <span class='totalPages'></span>"

//IronPDFsyntax
"Page {page} of {total-pages}"
C#

问题 4:未找到 JsReportBinary

**问题:**代码引用了JsReportBinary.GetBinary()

**解决方案:**完全删除——IronPDF 不需要外部二进制文件:

// DELETE this jsreport pattern:
.UseBinary(JsReportBinary.GetBinary())

//IronPDFneeds nothing—just create the renderer:
var renderer = new ChromePdfRenderer();
C#

迁移清单

迁移前

  • 确定所有jsreport using语句
  • 使用 Handlebars/JsRender 的列表模板(转换为 C# 字符串插值)
  • 记录当前使用的 Chrome 设置选项(页边距、纸张大小)
  • 检查是 Web 服务器模式还是实用程序模式(两者都会进入进程内运行)
  • 注意平台特定的二进制软件包(全部删除)
  • 获取IronPDF许可证密钥

软件包变更

  • 移除jsreport.Binary
  • 移除jsreport.Binary.Linux
  • 移除jsreport.Binary.OSX
  • 移除jsreport.Local
  • 移除jsreport.Types
  • 移除jsreport.Client
  • 安装IronPdf

代码更改

  • 在启动时添加许可证密钥配置
  • ChromePdfRenderer
  • 移除RenderRequest包装
  • 移除Template包装
  • 更新占位符语法 (<span class='pageNumber'>{page})
  • 将 Handlebars 替换为 C# 字符串插值
  • 移除StartAsync() / KillAsync()调用
  • 使用SaveAs()替换流复制

测试

  • 测试所有 PDF 生成路径
  • 验证页眉/页脚渲染效果 检查页码
  • 验证边距间距
  • 使用复杂的 CSS/JavaScript 页面进行测试
  • 基准性能

后迁移

  • 删除 jsreport 二进制文件
  • 如果不再需要,请移除 Node.js 依赖项
  • 更新部署脚本
  • 更新文档

请注意: jsreport 是其各自所有者的注册商标。 此网站与 jsreport 无关,不受其认可或赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。
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 天试用密钥
无需信用卡或创建账户