如何用 C# 从 jsreport 迁移到 IronPDF
从jsreport迁移到IronPDF可将您的 .NET PDF 工作流程从依赖 Node.js 的系统(带有外部二进制管理和单独的服务器进程)转变为完全在进程中运行的纯 .NET 库。 本指南提供了一个全面、循序渐进的迁移路径,为专业的 .NET 开发人员消除了基础架构的复杂性和 JavaScript 模板要求。
为什么要从jsreport迁移到 IronPDF?
jsreport面临的挑战
jsreport 引入了不属于纯 .NET 环境的复杂性:
- Node.js 依赖项:需要 Node.js 运行时和二进制文件,这给原本应该是一个简单的 .NET 应用程序增加了基础架构的复杂性。
2.外部二进制文件管理:必须通过单独的 NuGet 包(jsreport.Binary、jsreport.Binary.Linux、jsreport.Binary.OSX)下载和管理 Windows、Linux 和 OSX 平台特定的二进制文件。
3.独立服务器进程:作为实用程序或 Web 服务器运行——需要使用 StartAsync() 和 KillAsync() 生命周期方法进行额外的进程管理。
- 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()
开始之前
前提条件
- .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet 访问权限:能够安装 NuGet 包
- 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
许可配置
// 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"
确定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" .
完整的 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.TextHeader 或 HtmlHeader |
Chrome.FooterTemplate |
RenderingOptions.TextFooter 或 HtmlFooter |
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
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
jsreport 方法需要三个 NuGet 包(jsreport.Binary、jsreport.Local、jsreport.Types)、三个命名空间导入、仅异步执行、流畅的构建器链(LocalReporting().UseBinary().AsUtility().Create())、一个详细的 RenderRequest,其中包含嵌套的 Template 对象,该对象指定了 Recipe 和 Engine,以及使用 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
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
本示例突出了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
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
jsreport 方法需要将 Chrome 对象添加到 Template,设置 DisplayHeaderFooter = true,并使用带有特殊 CSS 类占位符 (<span class='pageNumber'></span>, <span class='totalPages'></span>) 的 HTML 模板。 页眉和页脚模板必须包含完整的内联样式。
IronPDF 提供更简洁的 TextHeaderFooter 配置,并为 CenterText、LeftText、RightText 和 FontSize 提供专用属性。 页码占位符使用更简单的 {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()
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
移除特定平台的二进制包
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
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}"
使用 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)
简化流处理
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
故障排除
问题 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()
问题 2:未找到渲染请求
问题:代码使用了 RenderRequest 和 Template 包装对象。
解决方案:直接将 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)
问题 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}"
问题 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();
迁移清单
迁移前
- 识别所有jsreport
using语句 - 使用 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()调用 - 将流复制替换为
BinaryData或SaveAs()
测试
- 测试所有 PDF 生成路径
- 验证页眉/页脚渲染效果 检查页码
- 验证边距间距
- 使用复杂的 CSS/JavaScript 页面进行测试
- 基准性能
后迁移
- 删除jsreport二进制文件
- 如果不再需要,请移除 Node.js 依赖项
- 更新部署脚本
- 更新文档

