跳至页脚内容
迁移指南

如何用 C# 从 jsreport 迁移到 IronPDF

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

为什么要从jsreport迁移到 IronPDF?

jsreport面临的挑战

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

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

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

3.独立服务器进程:作为实用程序或 Web 服务器运行——需要使用 StartAsync()KillAsync() 生命周期方法进行额外的进程管理。

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

5.复杂的请求结构:即使是简单的 PDF 生成,也需要详细的 RenderRequest 对象以及嵌套的 Template 配置。

6.许可限制:免费套餐限制模板数量; 缩放需要商业许可。

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

jsreport与IronPDF对比

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

对于计划在 2025 年和 2026 年之前采用 .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()

开始之前

前提条件

  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 软件包变更

# Removejsreportpackages
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
# Removejsreportpackages
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";
// 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"
$vbLabelText   $csharpLabel

确定jsreport的用法

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

完整的 API 参考

类映射

jsreport 类 IronPDF 同等产品
LocalReporting ChromePdfRenderer
ReportingService ChromePdfRenderer
RenderRequest 方法参数
Template 方法参数
Chrome RenderingOptions
Report PdfDocument
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.Content 第一个参数给 RenderHtmlAsPdf()
Template.Recipe = Recipe.ChromePdf (不需要)
Template.Engine = Engine.None (不需要)
Chrome.HeaderTemplate RenderingOptions.TextHeaderHtmlHeader
Chrome.FooterTemplate RenderingOptions.TextFooterHtmlFooter
Chrome.DisplayHeaderFooter (自动)
Chrome.MarginTop RenderingOptions.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!");
    }
}
// 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!");
    }
}
Imports jsreport.Binary
Imports jsreport.Local
Imports jsreport.Types
Imports System
Imports System.IO
Imports System.Threading.Tasks

Module Program
    Async Function Main(args As String()) As Task
        Dim rs = (New LocalReporting()) _
            .UseBinary(JsReportBinary.GetBinary()) _
            .AsUtility() _
            .Create()

        Dim report = Await rs.RenderAsync(New RenderRequest() With {
            .Template = New Template() With {
                .Recipe = Recipe.ChromePdf,
                .Engine = Engine.None,
                .Content = "<h1>Hello from jsreport</h1><p>This is a PDF document.</p>"
            }
        })

        Using fileStream = File.Create("output.pdf")
            report.Content.CopyTo(fileStream)
        End Using

        Console.WriteLine("PDF created successfully!")
    End Function
End Module
$vbLabelText   $csharpLabel

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!");
    }
}
// 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!");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main(args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello from IronPDF</h1><p>This is a PDF document.</p>")
        pdf.SaveAs("output.pdf")
        Console.WriteLine("PDF created successfully!")
    End Sub
End Class
$vbLabelText   $csharpLabel

jsreport 方法需要三个 NuGet 包(jsreport.Binaryjsreport.Localjsreport.Types)、三个命名空间导入、仅异步执行、流畅的构建器链(LocalReporting().UseBinary().AsUtility().Create())、一个详细的 RenderRequest,其中包含嵌套的 Template 对象,该对象指定了 RecipeEngine,以及使用 using 块手动将流复制到文件。

IronPDF 将其简化为一个 NuGet 包、一个命名空间、三行代码和同步执行。 ChromePdfRenderer.RenderHtmlAsPdf() 方法直接接受 HTML,并返回一个 PdfDocument,其中包含一个简单的 SaveAs() 方法。 有关其他渲染选项,请参阅 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!");
    }
}
// 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!");
    }
}
Imports jsreport.Binary
Imports jsreport.Local
Imports jsreport.Types
Imports System
Imports System.IO
Imports System.Threading.Tasks

Module Program
    Async Function Main(args As String()) As Task
        Dim rs = (New LocalReporting()) _
            .UseBinary(JsReportBinary.GetBinary()) _
            .AsUtility() _
            .Create()

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

        Using fileStream = File.Create("webpage.pdf")
            report.Content.CopyTo(fileStream)
        End Using

        Console.WriteLine("Webpage PDF created successfully!")
    End Function
End Module
$vbLabelText   $csharpLabel

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!");
    }
}
// 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!");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main(ByVal args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
        pdf.SaveAs("webpage.pdf")
        Console.WriteLine("Webpage PDF created successfully!")
    End Sub
End Class
$vbLabelText   $csharpLabel

本示例突出了jsreport的一个重要局限:没有直接的 URL 到 PDF 方法。jsreport代码必须使用嵌入在 HTML 内容中的 JavaScript 重定向变通方法 (window.location='https://example.com') 来捕获网页。 这种间接的方法在某些网站上可能会失败,并增加不必要的复杂性。

IronPDF 提供了一个专用的 RenderUrlAsPdf() 方法,可以直接渲染任何 URL,并完全执行 JavaScript 和支持现代 CSS。 无需变通方法,无需嵌入脚本,只需传递 URL 即可。 了解有关 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!");
    }
}
// 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!");
    }
}
Imports jsreport.Binary
Imports jsreport.Local
Imports jsreport.Types
Imports System
Imports System.IO
Imports System.Threading.Tasks

Module Program
    Async Function Main(args As String()) As Task
        Dim rs = New LocalReporting() _
            .UseBinary(JsReportBinary.GetBinary()) _
            .AsUtility() _
            .Create()

        Dim report = Await rs.RenderAsync(New RenderRequest() With {
            .Template = New Template() With {
                .Recipe = Recipe.ChromePdf,
                .Engine = Engine.None,
                .Content = "<h1>Document with Header and Footer</h1><p>Main content goes here.</p>",
                .Chrome = New Chrome() With {
                    .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 fileStream = File.Create("document_with_headers.pdf")
            report.Content.CopyTo(fileStream)
        End Using

        Console.WriteLine("PDF with headers and footers created successfully!")
    End Function
End Module
$vbLabelText   $csharpLabel

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!");
    }
}
// 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!");
    }
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System

Module Program
    Sub Main(args As String())
        Dim renderer As New ChromePdfRenderer()
        renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
            .CenterText = "Custom Header",
            .FontSize = 10
        }
        renderer.RenderingOptions.TextFooter = New TextHeaderFooter() With {
            .CenterText = "Page {page} of {total-pages}",
            .FontSize = 10
        }

        Dim 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!")
    End Sub
End Module
$vbLabelText   $csharpLabel

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

IronPDF 提供更简洁的 TextHeaderFooter 配置,并为 CenterTextLeftTextRightTextFontSize 提供专用属性。 页码占位符使用更简单的 {page}{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();
//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();
'jsreport(DELETE THIS):
Dim rs = New LocalReporting() _
    .UseBinary(JsReportBinary.GetBinary()) _
    .AsUtility() _
    .Create()

' Or for web server mode:
rs = New LocalReporting() _
    .UseBinary(JsReportBinary.GetBinary()) _
    .AsWebServer() _
    .Create()

Await rs.StartAsync()
' ... use rs ...
Await rs.KillAsync()
$vbLabelText   $csharpLabel

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

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

移除特定平台的二进制包

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

# DELETE these platform-specific packages:
dotnet remove package jsreport.Binary
dotnet remove package jsreport.Binary.Linux
dotnet remove package jsreport.Binary.OSX
# 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使用不同的语法:

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

//IronPDFplaceholders:
"{page}"
"{total-pages}"
"{date}"
"{html-title}"
//jsreportplaceholders:
"<span class='pageNumber'></span>"  // or {#pageNum}
"<span class='totalPages'></span>"  // or {#numPages}

//IronPDFplaceholders:
"{page}"
"{total-pages}"
"{date}"
"{html-title}"
'jsreportplaceholders:
"<span class='pageNumber'></span>"  ' or {#pageNum}
"<span class='totalPages'></span>"  ' or {#numPages}

'IronPDFplaceholders:
"{page}"
"{total-pages}"
"{date}"
"{html-title}"
$vbLabelText   $csharpLabel

使用 C# 字符串插值替换手柄

jsreport 通常使用 Handlebars 模板,代码如下:Engine.Handlebars:

//jsreportHandlebars (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);
//jsreportHandlebars (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);
Imports IronPdf

' jsreportHandlebars (DELETE THIS):
Dim template As New Template With {
    .Content = "<h1>Hello, {{name}}</h1>",
    .Engine = Engine.Handlebars
}

Dim data = New With {.name = "World"}

' IronPDF with VB.NET string interpolation:
Dim name As String = "World"
Dim html As String = $"<h1>Hello, {name}</h1>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
$vbLabelText   $csharpLabel

简化流处理

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

//jsreportstream 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;
//jsreportstream 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;
Imports System.IO

'jsreportstream handling (DELETE THIS):
Using fileStream As FileStream = File.Create("output.pdf")
    report.Content.CopyTo(fileStream)
End Using

' Or for byte array:
Using memoryStream As New MemoryStream()
    Await report.Content.CopyToAsync(memoryStream)
    Return memoryStream.ToArray()
End Using

'IronPDFdirect access:
pdf.SaveAs("output.pdf")
' Or:
Dim bytes As Byte() = pdf.BinaryData
$vbLabelText   $csharpLabel

故障排除

问题 1:未找到本地报告

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

解决方案:替换为 ChromePdfRenderer:

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

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

// IronPDF
var renderer = new ChromePdfRenderer();
' jsreport
Dim rs = New LocalReporting().UseBinary().AsUtility().Create()

' IronPDF
Dim renderer = New ChromePdfRenderer()
$vbLabelText   $csharpLabel

问题 2:未找到渲染请求

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

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

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

// IronPDF
var pdf = renderer.RenderHtmlAsPdf(html);
// jsreport
await rs.RenderAsync(new RenderRequest { Template = new Template { Content = html } });

// IronPDF
var pdf = renderer.RenderHtmlAsPdf(html);
Imports System.Threading.Tasks

' jsreport
Await rs.RenderAsync(New RenderRequest With {.Template = New Template With {.Content = html}})

' IronPDF
Dim pdf = renderer.RenderHtmlAsPdf(html)
$vbLabelText   $csharpLabel

问题 3:页码未显示

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

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

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

//IronPDFsyntax
"Page {page} of {total-pages}"
//jsreportsyntax (won't work)
"Page <span class='pageNumber'></span> of <span class='totalPages'></span>"

//IronPDFsyntax
"Page {page} of {total-pages}"
'jsreportsyntax (won't work)
"Page <span class='pageNumber'></span> of <span class='totalPages'></span>"

'IronPDFsyntax
"Page {page} of {total-pages}"
$vbLabelText   $csharpLabel

问题 4:未找到 JsReportBinary

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

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

// DELETE thisjsreportpattern:
.UseBinary(JsReportBinary.GetBinary())

//IronPDFneeds nothing—just create the renderer:
var renderer = new ChromePdfRenderer();
// DELETE thisjsreportpattern:
.UseBinary(JsReportBinary.GetBinary())

//IronPDFneeds nothing—just create the renderer:
var renderer = new ChromePdfRenderer();
$vbLabelText   $csharpLabel

迁移清单

迁移前

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

软件包变更

  • 删除 jsreport.Binary
  • 删除 jsreport.Binary.Linux
  • 删除 jsreport.Binary.OSX
  • 删除 jsreport.Local
  • 删除 jsreport.Types
  • 删除 jsreport.Client 包 安装 IronPdf 软件包

代码更改

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

测试

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

后迁移

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

Curtis Chau
技术作家

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

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我