如何在 C# 中將 PDF 點陣化為圖像
從jsreport遷移到IronPDF可將您的.NET PDF工作流程從依賴Node.js的系統與外部二進位管理和獨立的伺服器進程轉變為純粹的.NET程式庫,完全在進程中運行。 本指南提供了一個全面的逐步遷移路徑,為專業的.NET開發者消除了基礎設施的複雜性和JavaScript模板需求。
為什麼要從jsreport遷移到IronPDF
jsreport的挑戰
jsreport引入了不屬於純.NET環境的複雜性:
-
Node.js依賴:需要Node.js運行時和二進位,增加了本應簡單的.NET應用程式的基礎設施複雜性。
-
外部二進位管理:必須通過獨立的NuGet套件下載和管理特定於Windows、Linux和OSX的二進位 (
jsreport.Binary,jsreport.Binary.Linux,jsreport.Binary.OSX)。 -
獨立的伺服器進程:以公用程式或網頁伺服器的形式運行—需要額外的進程管理方法
StartAsync()和KillAsync()周期方法。 -
JavaScript模板:強迫學習Handlebars、JsRender或其他JavaScript模板系統而不是使用本地C#功能。
-
複雜的請求結構:即使是簡單的PDF生成也需要冗長的
Template配置。 -
授權限制:免費版本限於每個實例5個模板; 商業使用超出這個需要Enterprise授權(每實例年費$395)或Enterprise Scale(每年$1,295,免版稅跨實例)。 See jsreport.net/buy.
- 基於流的輸出:返回流需要手動的文件操作和記憶體流管理。
jsreport與IronPDF對比
| 功能 | jsreport | IronPDF |
|---|---|---|
| 運行時 | Node.js + .NET | 純.NET |
| 二進位管理 | 手動 (jsreport.Binary套件) | 自動 |
| 伺服器進程 | 需要(公用程式或網頁伺服器) | 進程中 |
| 模板 | JavaScript (Handlebars, etc.) | C# (Razor, 字串插值) |
| API風格 | 冗長的請求物件 | 乾淨的流暢方法 |
| 輸出 | 流 | PdfDocument物件 |
| PDF操作 | 有限 | 廣泛(合併,拆分,編輯) |
| 異步支援 | 僅限非同步 | 同步和非同步皆可 |
對於計劃採用.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 Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet存取: 有能力安裝NuGet套件
- 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
# 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
授權配置
// 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 all jsreport references
grep -r "using jsreport\|LocalReporting\|RenderRequest\|RenderAsync" --include="*.cs" .
grep -r "JsReportBinary\|Template\|Recipe\|Engine\." --include="*.cs" .
# Find all jsreport references
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) or pdf.BinaryData |
RenderRequest屬性映射
| jsreport模板屬性 | IronPDF等價 |
|---|---|
Template.Content |
RenderHtmlAsPdf()的第一個參數 |
Template.Recipe = Recipe.ChromePdf |
(不需要) |
Template.Engine = Engine.None |
(不需要) |
Chrome.HeaderTemplate |
RenderingOptions.TextHeader or HtmlHeader |
Chrome.FooterTemplate |
RenderingOptions.TextFooter or 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
之後(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, RenderRequest 與巢狀的Recipe 和using塊手動將流複製到文件。
IronPDF將其縮減到一個NuGet套件,一個命名空間,三行程式碼和同步執行。 SaveAs()方法。 查看HTML到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
之後(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可以通過設置請求上的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!");
}
}
// 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
之後(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方法需要將<span class='pageNumber'></span>, <span class='totalPages'></span>)的HTML範本。 頁眉和頁腳模板必須包含完整的內聯樣式。
IronPDF提供了更清晰的TextHeaderFooter配置,提供專用屬性 CenterText, LeftText, RightText 和 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();
// 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使用不同的語法:
// jsreport placeholders:
"<span class='pageNumber'></span>" // or {#pageNum}
"<span class='totalPages'></span>" // or {#numPages}
//IronPDFplaceholders:
"{page}"
"{total-pages}"
"{date}"
"{html-title}"
// jsreport placeholders:
"<span class='pageNumber'></span>" // or {#pageNum}
"<span class='totalPages'></span>" // or {#numPages}
//IronPDFplaceholders:
"{page}"
"{total-pages}"
"{date}"
"{html-title}"
' jsreport placeholders:
"<span class='pageNumber'></span>" ' or {#pageNum}
"<span class='totalPages'></span>" ' or {#numPages}
' IronPDF placeholders:
"{page}"
"{total-pages}"
"{date}"
"{html-title}"
用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);
// 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);
Imports System
' jsreport Handlebars (DELETE THIS):
Dim Template As New Template With {
.Content = "<h1>Hello, {{name}}</h1>",
.Engine = Engine.Handlebars
}
Dim Data = New With {Key .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返回的流需要手動複製:
// 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;
// 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;
Imports System.IO
' jsreport stream 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
' IronPDF direct access:
pdf.SaveAs("output.pdf")
' Or:
Dim bytes As Byte() = pdf.BinaryData
故障排除
問題1:找不到LocalReporting
問題:程式碼引用了LocalReporting類別,而在IronPDF中不存在。
解決方案:替換為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佔位符語法:
// jsreport syntax (won't work)
"Page <span class='pageNumber'></span> of <span class='totalPages'></span>"
//IronPDFsyntax
"Page {page} of {total-pages}"
// jsreport syntax (won't work)
"Page <span class='pageNumber'></span> of <span class='totalPages'></span>"
//IronPDFsyntax
"Page {page} of {total-pages}"
' jsreport syntax (won't work)
"Page <span class='pageNumber'></span> of <span class='totalPages'></span>"
' IronPDF syntax
"Page {page} of {total-pages}"
問題4:找不到JsReportBinary
問題:程式碼參考了JsReportBinary.GetBinary()。
解決方案:完全刪除—IеonPDF不需要外部二進位文件:
// DELETE this jsreport pattern:
.UseBinary(JsReportBinary.GetBinary())
//IronPDFneeds nothing—just create the renderer:
var renderer = new ChromePdfRenderer();
// DELETE this jsreport pattern:
.UseBinary(JsReportBinary.GetBinary())
//IronPDFneeds nothing—just create the renderer:
var renderer = new ChromePdfRenderer();
' DELETE this jsreport pattern:
'.UseBinary(JsReportBinary.GetBinary())
' IronPDF needs nothing—just create the renderer:
Dim renderer As New ChromePdfRenderer()
遷移檢查表
遷移前
- 識別所有jsreport
using語句 - 列出使用Handlebars/JsRender的模板(轉換為C#字串插值)
- 記錄當前使用的Chrome選項(邊距,紙張大小)
- 檢查網頁伺服器與公用程式模式(兩者均變為進程內)
- 記錄特定平台的二進位包(全部刪除)
- 獲得IronPDF授權金鑰
套件變更
- 移除
jsreport.Binary套件 - 移除
jsreport.Binary.Linux套件 - 移除
jsreport.Binary.OSX套件 - 移除
jsreport.Local套件 - 移除
jsreport.Types套件 - 移除
jsreport.Client套件 - 安裝
IronPdf套件
程式碼變更
- 在啟動時加入授權金鑰配置
- 將
ChromePdfRenderer - 移除
RenderRequest包裝 - 移除
Template包裝 - 更新佔位符語法 (
<span class='pageNumber'>→{page}) - 用C#字串插值替代Handlebars
- 移除
StartAsync()/KillAsync()調用 - 將流複製替換為
SaveAs()
測試
- 測試所有PDF生成流程
- 驗證頁眉/頁腳的渲染
- 檢查頁碼
- 驗證邊距間距
- 用複雜的CSS/JavaScript頁面進行測試
- 基準測試性能
遷移後
- 刪除jsreport二進位文件
- 如果不再需要,則移除Node.js依賴項
- 更新部署腳本
- 更新文件

