如何用 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.Binary 套件) | 自動化 |
| 伺服器流程 | 必需 (公用程式或網路伺服器) | 處理中 |
| 模板製作 | JavaScript (Handlebars 等) | C# (Razor、字串插值) |
| API 風格 | 繁複的請求物件 | 乾淨流暢的方法 |
| 輸出 | 流 | PdfDocument 物件 |
| PDF 操作 | 限額 | 廣泛(合併、分割、編輯) |
| 同步支援 | 僅限同步 | 同步和同步 |
對於計劃在 2025 年和 2026 年之前採用 .NET 10 和 C# 14 的團隊而言,IronPDF 可作為原生 .NET 函式庫提供面向未來的基礎,而無需外部執行時依賴。
遷移複雜性評估
按功能估計的工作量
| 特點 | 遷移複雜性 |
|---|---|
| HTML 至 PDF | 非常低 |
| URL 至 PDF | 非常低 |
| 頁首/頁尾 | 低 |
| 頁面設定 | 低 |
| 伺服器生命週期 | 低 |
| 二進位管理 | 低 |
範式轉移
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取得您的許可證密鑰。
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 |
RenderRequest 屬性對應
| 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)、三個命名空間導入、僅異步執行、流暢的構建器鏈(@@--CODE-17830--@@)、包含巢狀 Template 對象的冗長 RenderRequest(指定了 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。 頁頭與頁尾的範本必須包含完整的內嵌式樣。
IronPDF 提供更簡潔的 TextHeaderFooter 配置,並為 CenterText、LeftText、RightText 和 FontSize--CODE-17849--@@ 和 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:LocalReporting 未找到
問題:程式碼引用了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
問題:程式碼使用了 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 依賴項
- 更新部署腳本
- 更新文件

