
如何使用 C# 在 Blazor Server 中將 Razor 轉換為 PDF
從Kaizen.io HTML-to-PDF遷移到IronPDF將一個暴露在HTTP上的自託管Docker容器替換為一個進程內的.NET程式庫。 Kaizen.io HTML-to-PDF僅以Docker影像POST /html-to-pdf —— 沒有官方的.NET SDK或NuGet套件,因此每個C#調用都必須手動對在運行的容器進行HttpClient。 本指南將逐步介紹如何將該模式替換為IronPDF的ChromePdfRenderer。
為何從Kaizen.io遷移到IronPDF
容器API的挑戰
Kaizen.io HTML-to-PDF是帶有一個故意的小型v1.x API的Docker容器,而C#整合則是您自己在HttpClient上構建的。 這種形態在生產中有實際的限制:
-
容器運作: 您需要運行、監控和更新
kaizenio.azurecr.io/html-to-pdf:latest,它必須在應用程式可以存取的某個地方 —— 本地Docker、側車或獨立主機。 -
沒有.NET SDK: 每個C#調用都必須手動卷動
HttpClientPOST + JSON。 沒有IntelliSense,請求形狀也沒有編譯時檢查。 -
小型v1.x API表面: 文件化的JSON主體僅接受一個
html字段。 URL-to-PDF、自訂樣式表、頁眉/頁腳、頁面大小、方向和邊距被列為路線圖項目,而不是交付的功能 —— 非HTML字串的呈現都必須在HTML內表達,通常通過@pageCSS和絕對定位的div實現。 -
沒有頁碼支持: API沒有
{page}/{total}佔位符,因此無法在伺服器端生成"第X頁,共Y頁"的頁腳。 -
每個PDF的HTTP往返: 即使容器在
localhost運行,每份PDF都要支付JSON序列化和socket跳的代價。 -
免費層上的浮水印: 如果容器上未設置
KAIZEN_PDF_LICENSE環境變數,輸出將會帶有浮水印。
Kaizen.io與IronPDF的比較
| 功能 | Kaizen.io HTML-to-PDF | IronPDF |
|---|---|---|
| 分發 | Docker影像kaizenio.azurecr.io/html-to-pdf | NuGet IronPdf |
| C#整合 | 手動卷動HttpClient POST (無SDK) | 強型別ChromePdfRenderer API |
| 過程模型 | 過程外容器 | 進程中 |
| 端點介面 (v1.x) | POST /html-to-pdf 與 { "html": ... } | HTML、文件、URL方法 |
| URL輸入 | 路線圖 | RenderUrlAsPdf(url) |
| 頁眉 / 頁腳 | v1.x API不支持; 通過固定位置CSS假設 | TextHeader/Footer 和 HtmlHeader/Footer |
| 頁碼 | 不支持 | {page} 和 {total-pages}佔位符 |
| 頁面大小 / 方向 | 在HTML中嵌入@page CSS | RenderingOptions.PaperSize 等等。 |
| 授權 | 一次性授權; 浮水印的免費層 | 商業(年度或永久) |
對於標準化現代.NET的團隊,IronPDF在請求路徑中刪除了側車容器和HTTP跳,同時公開了一個強型別的配置表面。
遷移複雜性評估
功能的預估努力程度
| 功能 | 遷移複雜性 |
|---|---|
| 基本HTML To PDF | 非常低 |
| HTML文件 To PDF | 非常低 |
| URL到PDF | 低 (Kaizen v1.x沒有URL端點 —— 整體替換掉替代方案) |
| 頁眉/頁腳 | 中等 (假設的CSS div替換為真實的頁眉區) |
| 頁碼 | 新能力 (Kaizen v1.x中不可用) |
| 頁面設置 | 低 (@page CSS移動到RenderingOptions) |
範式轉變
根本性轉變是從外部進程HTTP呼叫Docker容器到進程內呈現:
Kaizen.io: HttpClient.PostAsync("http://.../html-to-pdf", { html }) → byte[]
IronPDF: ChromePdfRenderer → RenderHtmlAsPdf(html) → PdfDocument
開始之前
前提條件
- .NET環境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5+
- NuGet存取: 有能力安裝NuGet套件
- IronPDF授權: 從ironpdf.com獲取您的授權金鑰
套件變更
沒有Kaizen NuGet套件需要移除 —— Kaizen僅作為Docker影像提供。 停止容器並新增IronPDF套件:
# Stop and remove the running Kaizen container (if any)
docker stop kaizen-pdf
docker rm kaizen-pdf
# 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.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"識別Kaizen.io的使用
由於Kaizen沒有SDK,進入它的調用看起來像通用的HttpClient POST。 搜尋端點、影像名稱和授權環境變數,而不是命名空間:
grep -r "html-to-pdf\|KAIZEN_PDF_LICENSE\|kaizenio.azurecr.io\|localhost:8080" \
--include="*.cs" --include="*.json" --include="*.yml" .
完整API參考
概念映射
沒有Kaizen .NET類來映射 —— 只有JSON請求形狀和您在其上構建的規範。
| Kaizen.io 概念 | IronPDF等價 |
|---|---|
HttpClient + POST /html-to-pdf | ChromePdfRenderer |
JSON { "html": "..." } 主體 | RenderHtmlAsPdf(string html) |
| (No URL field in v1.x) | RenderUrlAsPdf(string url) |
| (No file field in v1.x) | RenderHtmlFileAsPdf(string path) |
嵌入@page CSS以獲得大小 | RenderingOptions.PaperSize |
嵌入@page CSS以獲得方向 | RenderingOptions.PaperOrientation |
嵌入 @page { margin: ... } | RenderingOptions.MarginTop/Bottom/Left/Right |
固定位置<div class='header'> 假設 | RenderingOptions.TextHeader / HtmlHeader |
固定位置<div class='footer'> 假設 | RenderingOptions.TextFooter / HtmlFooter |
HttpClient.PostAsync | RenderHtmlAsPdfAsync |
容器環境變數KAIZEN_PDF_LICENSE | IronPdf.License.LicenseKey |
HTTP byte[] 回應 | pdf.BinaryData / pdf.SaveAs(path) |
佔位符映射
Kaizen v1.x沒有伺服器端佔位符。 如果您之前將字串手動替換到HTML中後再POST,請切換到IronPDF的呈現時間佔位符:
| 您以前做好了什麼 | IronPDF 佔位符 |
|---|---|
html.Replace("{page}", currentPage.ToString()) | {page} |
html.Replace("{total}", total.ToString()) | {total-pages} |
html.Replace("{date}", DateTime.Now.ToShortDateString()) | {date} |
html.Replace("{title}", docTitle) | {html-title} |
程式碼遷移範例
範例1:基本HTML到PDF
以前 (Kaizen.io —— 向容器POST JSON):
// Container must be running:
// docker run -d -p 8080:8080 -e KAIZEN_PDF_LICENSE=... \
// kaizenio.azurecr.io/html-to-pdf:latest
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
var payload = JsonSerializer.Serialize(new { html = "<html><body><h1>Hello World</h1></body></html>" });
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);
response.EnsureSuccessStatusCode();
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("output.pdf", pdfBytes);
}
}// Container must be running:
// docker run -d -p 8080:8080 -e KAIZEN_PDF_LICENSE=... \
// kaizenio.azurecr.io/html-to-pdf:latest
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
var payload = JsonSerializer.Serialize(new { html = "<html><body><h1>Hello World</h1></body></html>" });
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);
response.EnsureSuccessStatusCode();
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("output.pdf", pdfBytes);
}
}Imports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using http As New HttpClient()
Dim payload = JsonSerializer.Serialize(New With {.html = "<html><body><h1>Hello World</h1></body></html>"})
Dim content As New StringContent(payload, Encoding.UTF8, "application/json")
Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", content)
response.EnsureSuccessStatusCode()
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
File.WriteAllBytes("output.pdf", pdfBytes)
End Using
End Function
End ModuleImports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using http As New HttpClient()
Dim payload = JsonSerializer.Serialize(New With {.html = "<html><body><h1>Hello World</h1></body></html>"})
Dim content As New StringContent(payload, Encoding.UTF8, "application/json")
Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", content)
response.EnsureSuccessStatusCode()
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
File.WriteAllBytes("output.pdf", pdfBytes)
End Using
End Function
End Module之後(IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System.IO;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System.IO;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}Imports IronPdf
Imports System.IO
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html = "<html><body><h1>Hello World</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End ClassImports IronPdf
Imports System.IO
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html = "<html><body><h1>Hello World</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End ClassKaizen.io的方式序列化JSON, 將其POST到容器的REST端點,檢查狀態程式碼,將回應讀取為位元組,然後將這些位元組寫入磁碟。 IronPDF的ChromePdfRenderer在進程內運行 —— SaveAs()方法,因此迴圈和手動位元組處理消失。 查看HTML到PDF文件以獲取其他渲染選項。
範例2:帶頁面設置的HTML文件轉為PDF
Kaizen v1.x沒有文件端點和頁面佈局字段 —— 您自己讀取文件並將頁面大小/方向嵌入@page CSS。
以前 (Kaizen.io):
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var body = File.ReadAllText("input.html");
var html = "<style>@page { size: A4 portrait; }</style>" + body;
using var http = new HttpClient();
var payload = JsonSerializer.Serialize(new { html });
var response = await http.PostAsync(
"http://localhost:8080/html-to-pdf",
new StringContent(payload, Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();
File.WriteAllBytes("document.pdf", await response.Content.ReadAsByteArrayAsync());
}
}using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var body = File.ReadAllText("input.html");
var html = "<style>@page { size: A4 portrait; }</style>" + body;
using var http = new HttpClient();
var payload = JsonSerializer.Serialize(new { html });
var response = await http.PostAsync(
"http://localhost:8080/html-to-pdf",
new StringContent(payload, Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();
File.WriteAllBytes("document.pdf", await response.Content.ReadAsByteArrayAsync());
}
}Imports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Dim body = File.ReadAllText("input.html")
Dim html = "<style>@page { size: A4 portrait; }</style>" & body
Using http As New HttpClient()
Dim payload = JsonSerializer.Serialize(New With {Key .html = html})
Dim response = Await http.PostAsync(
"http://localhost:8080/html-to-pdf",
New StringContent(payload, Encoding.UTF8, "application/json"))
response.EnsureSuccessStatusCode()
File.WriteAllBytes("document.pdf", Await response.Content.ReadAsByteArrayAsync())
End Using
End Function
End ModuleImports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Dim body = File.ReadAllText("input.html")
Dim html = "<style>@page { size: A4 portrait; }</style>" & body
Using http As New HttpClient()
Dim payload = JsonSerializer.Serialize(New With {Key .html = html})
Dim response = Await http.PostAsync(
"http://localhost:8080/html-to-pdf",
New StringContent(payload, Encoding.UTF8, "application/json"))
response.EnsureSuccessStatusCode()
File.WriteAllBytes("document.pdf", Await response.Content.ReadAsByteArrayAsync())
End Using
End Function
End Module之後(IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("document.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("document.pdf");
}
}Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait
Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
pdf.SaveAs("document.pdf")
End Sub
End ClassImports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait
Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
pdf.SaveAs("document.pdf")
End Sub
End ClassRenderHtmlFileAsPdf() 直接讀取文件,頁面大小和方向從內嵌@page CSS移動到RenderingOptions 屬性。
範例3:帶頁眉和頁腳的URL轉為PDF
Kaizen v1.x沒有ConvertUrl、沒有頁眉/頁腳字段,也沒有頁碼佔位符。 替代方案是自己抓取頁面,並用@page CSS和固定位置的div包裝來假設頁眉/頁腳 —— 沒有辦法呈現頁碼。
以前 (Kaizen.io):
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
var page = await http.GetStringAsync("https://example.com");
var html = $@"<!doctype html><html><head><style>
@page {{margin: 20mm;}}
.h {{position: fixed; top: -15mm; left: 0; right: 0; text-align: center;}}
.f {{position: fixed; bottom: -15mm; left: 0; right: 0; text-align: center;}}
</style></head><body>
<div class='h'>Company Header</div>
<div class='f'>Footer (page numbers unsupported in Kaizen v1.x)</div>
{page}
</body></html>";
var payload = JsonSerializer.Serialize(new { html });
var response = await http.PostAsync(
"http://localhost:8080/html-to-pdf",
new StringContent(payload, Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();
File.WriteAllBytes("webpage.pdf", await response.Content.ReadAsByteArrayAsync());
}
}using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
var page = await http.GetStringAsync("https://example.com");
var html = $@"<!doctype html><html><head><style>
@page {{margin: 20mm;}}
.h {{position: fixed; top: -15mm; left: 0; right: 0; text-align: center;}}
.f {{position: fixed; bottom: -15mm; left: 0; right: 0; text-align: center;}}
</style></head><body>
<div class='h'>Company Header</div>
<div class='f'>Footer (page numbers unsupported in Kaizen v1.x)</div>
{page}
</body></html>";
var payload = JsonSerializer.Serialize(new { html });
var response = await http.PostAsync(
"http://localhost:8080/html-to-pdf",
new StringContent(payload, Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();
File.WriteAllBytes("webpage.pdf", await response.Content.ReadAsByteArrayAsync());
}
}Imports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using http = New HttpClient()
Dim page = Await http.GetStringAsync("https://example.com")
Dim html = $"<!doctype html><html><head><style>
@page {{margin: 20mm;}}
.h {{position: fixed; top: -15mm; left: 0; right: 0; text-align: center;}}
.f {{position: fixed; bottom: -15mm; left: 0; right: 0; text-align: center;}}
</style></head><body>
<div class='h'>Company Header</div>
<div class='f'>Footer (page numbers unsupported in Kaizen v1.x)</div>
{page}
</body></html>"
Dim payload = JsonSerializer.Serialize(New With {html})
Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", New StringContent(payload, Encoding.UTF8, "application/json"))
response.EnsureSuccessStatusCode()
File.WriteAllBytes("webpage.pdf", Await response.Content.ReadAsByteArrayAsync())
End Using
End Function
End ModuleImports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using http = New HttpClient()
Dim page = Await http.GetStringAsync("https://example.com")
Dim html = $"<!doctype html><html><head><style>
@page {{margin: 20mm;}}
.h {{position: fixed; top: -15mm; left: 0; right: 0; text-align: center;}}
.f {{position: fixed; bottom: -15mm; left: 0; right: 0; text-align: center;}}
</style></head><body>
<div class='h'>Company Header</div>
<div class='f'>Footer (page numbers unsupported in Kaizen v1.x)</div>
{page}
</body></html>"
Dim payload = JsonSerializer.Serialize(New With {html})
Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", New StringContent(payload, Encoding.UTF8, "application/json"))
response.EnsureSuccessStatusCode()
File.WriteAllBytes("webpage.pdf", Await response.Content.ReadAsByteArrayAsync())
End Using
End Function
End Module之後(IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader.CenterText = "Company Header";
renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}";
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader.CenterText = "Company Header";
renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}";
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader.CenterText = "Company Header"
renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}"
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End ClassImports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader.CenterText = "Company Header"
renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}"
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End ClassRenderUrlAsPdf() 直接抓取並渲染URL —— 無需客戶端頁面抓取 —— 假設的固定位置div被TextHeader / TextFooter區域替換。 頁碼通過{total-pages}佔位符生成,Kaizen v1.x不提供這些。了解更多關於URL到PDF轉換和頁眉和頁腳。
關鍵遷移注意事項
授權在程式碼中,而不是在容器中
Kaizen的授權是通過Docker容器上的KAIZEN_PDF_LICENSE環境變數配置。 IronPDF的授權是在應用程式啟動時設置一次的靜態屬性:
// DELETE the Kaizen container env var:
// docker run ... -e KAIZEN_PDF_LICENSE=... kaizenio.azurecr.io/html-to-pdf
// IronPDF: set once at startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();// DELETE the Kaizen container env var:
// docker run ... -e KAIZEN_PDF_LICENSE=... kaizenio.azurecr.io/html-to-pdf
// IronPDF: set once at startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();' DELETE the Kaizen container env var:
' docker run ... -e KAIZEN_PDF_LICENSE=... kaizenio.azurecr.io/html-to-pdf
' IronPDF: set once at startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer As New ChromePdfRenderer()' DELETE the Kaizen container env var:
' docker run ... -e KAIZEN_PDF_LICENSE=... kaizenio.azurecr.io/html-to-pdf
' IronPDF: set once at startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer As New ChromePdfRenderer()佔位符語法
如果您之前將字串手動替換到HTML中後再POST,請切換到IronPDF的呈現時間佔位符:
{page}(不變){total}→{total-pages}{title}→{html-title}{date}→{date}(不變)
返回型別變更
Kaizen通過HTTP返回原始位元組。IronPDF返回一個PdfDocument:
// Kaizen.io returns byte[] via HTTP
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("output.pdf", pdfBytes);
//IronPDFreturns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf"); // Direct save
byte[] bytes = pdf.BinaryData; // Or get bytes if needed// Kaizen.io returns byte[] via HTTP
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("output.pdf", pdfBytes);
//IronPDFreturns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf"); // Direct save
byte[] bytes = pdf.BinaryData; // Or get bytes if needed' Kaizen.io returns byte() via HTTP
Dim pdfBytes As Byte() = Await response.Content.ReadAsByteArrayAsync()
File.WriteAllBytes("output.pdf", pdfBytes)
' IronPDF returns PdfDocument
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf") ' Direct save
Dim bytes As Byte() = pdf.BinaryData ' Or get bytes if needed' Kaizen.io returns byte() via HTTP
Dim pdfBytes As Byte() = Await response.Content.ReadAsByteArrayAsync()
File.WriteAllBytes("output.pdf", pdfBytes)
' IronPDF returns PdfDocument
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf") ' Direct save
Dim bytes As Byte() = pdf.BinaryData ' Or get bytes if needed刪除HTTP管道
一旦渲染器在進程中,支持程式碼就消失了:
// DELETE all of:
// - HttpClient lifetime management
// - JSON serialization of { html }
// - response.EnsureSuccessStatusCode() / status-code branches
// - "container unreachable" retry/backoff
// - ReadAsByteArrayAsync()
// Replaced with a single in-process call:
var pdf = renderer.RenderHtmlAsPdf(html);// DELETE all of:
// - HttpClient lifetime management
// - JSON serialization of { html }
// - response.EnsureSuccessStatusCode() / status-code branches
// - "container unreachable" retry/backoff
// - ReadAsByteArrayAsync()
// Replaced with a single in-process call:
var pdf = renderer.RenderHtmlAsPdf(html);netnet故障排除
問題1:沒有HtmlToPdfConverter類
問題: 沒有HtmlToPdfConverter類可供替換 —— Kaizen根本沒有.NET SDK。
解決方案: 遷移是從ChromePdfRenderer:
// Kaizen.io: hand-rolled HTTP
using var http = new HttpClient();
var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);
// IronPDF: in-process renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);// Kaizen.io: hand-rolled HTTP
using var http = new HttpClient();
var response = await http.PostAsync("http://localhost:8080/html-to-pdf", content);
// IronPDF: in-process renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);Imports System.Net.Http
Imports IronPdf
' Kaizen.io: hand-rolled HTTP
Using http As New HttpClient()
Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", content)
End Using
' IronPDF: in-process renderer
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)Imports System.Net.Http
Imports IronPdf
' Kaizen.io: hand-rolled HTTP
Using http As New HttpClient()
Dim response = Await http.PostAsync("http://localhost:8080/html-to-pdf", content)
End Using
' IronPDF: in-process renderer
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)問題2:選項物件去哪裡了?
問題: Kaizen v1.x沒有ConversionOptions —— 頁面佈局是內嵌@page CSS,頁眉/頁腳是固定位置的div。
解決方案: 將該配置移至渲染器上的RenderingOptions:
// Before: <style>@page { size: A4 portrait; margin: 20mm; }</style>
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;// Before: <style>@page { size: A4 portrait; margin: 20mm; }</style>
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;' Before: <style>@page { size: A4 portrait; margin: 20mm; }</style>
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20' Before: <style>@page { size: A4 portrait; margin: 20mm; }</style>
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Portrait
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20問題3:頁碼無法呈現
問題: Kaizen v1.x沒有{page} / {total}佔位符支持,所以任何預遷移的"第X頁,共Y頁"頁腳要麼缺失,要麼是靜態文字。
解決方案: 使用IronPDF的頁眉/頁腳佔位符:
renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
CenterText = "Page {page} of {total-pages}"
};renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
CenterText = "Page {page} of {total-pages}"
};renderer.RenderingOptions.TextFooter = New TextHeaderFooter With {
.CenterText = "Page {page} of {total-pages}"
}renderer.RenderingOptions.TextFooter = New TextHeaderFooter With {
.CenterText = "Page {page} of {total-pages}"
}如果您之前在POST之前手動替換了您自己的程式碼中的{total},請刪除該替換 —— IronPDF在呈現時解決{total-pages}。
問題4:容器連接錯誤
問題: 處理"容器無法到達"/端口-8080錯誤的程式碼路徑。
解決方案: IronPDF在進程中運行 —— 沒有端點可以連接。 刪除連接錯誤處理。
問題5:首次渲染緩慢
問題: 首次PDF生成耗時1-3秒。
解決方案: IronPDF在第一次使用時初始化Chromium。 在應用程式啟動時進行加熱:
// In Program.cs or Startup.cs:
new ChromePdfRenderer().RenderHtmlAsPdf("<html></html>");// In Program.cs or Startup.cs:
new ChromePdfRenderer().RenderHtmlAsPdf("<html></html>");' In Program.vb or Startup.vb:
Call New ChromePdfRenderer().RenderHtmlAsPdf("<html></html>")' In Program.vb or Startup.vb:
Call New ChromePdfRenderer().RenderHtmlAsPdf("<html></html>")遷移檢查表
遷移前
- 定位每個Kaizen調用點(搜尋
localhost:8080) - 文件內嵌的
@pageCSS,用於大小、方向、邊距 - 文件虛假的頁眉/頁腳div(固定位置帶負偏移)
- 列出任何客戶端的佔位符替換(
html.Replace("{page}", ...)等。) - 註意容器生命周期:拉取、運行、重啟、授權環境變數
- 獲得IronPDF授權金鑰
容器拆解
- 停止並刪除運行中的Kaizen容器
docker stop kaizen-pdf && docker rm kaizen-pdf - 從CI/CD中刪除Kaizen拉取/運行步驟
- 從secrets/env中刪除
KAIZEN_PDF_LICENSE - 安裝
IronPdfNuGet套件dotnet add package IronPdf
程式碼變更
- 在啟動時加入授權金鑰配置
- 用
HttpClientPOST - 將嵌入的
@pageCSS移入RenderingOptions屬性 - 用
RenderHtmlAsPdf()/RenderHtmlFileAsPdf()/RenderUrlAsPdf()替換JSON POST - 用
HtmlHeader/Footer替換虛假頁眉/頁腳div - 更新佔位符語法(
{total}→{title}→{html-title}) - 用
byte[]HTTP主體 - 使用
File.WriteAllBytes() - 刪除容器可達性錯誤處理和重試/退避
測試
- 測試所有PDF生成流程
- 驗證頁眉/頁腳的呈現和頁碼(新功能)
- 驗證邊距、頁面大小和方向
- 測試脫機操作(不需要容器)
遷移後
- 拆除Kaizen容器基礎結構
- 更新環境變數 / 密鑰
- 從監控/警報中刪除容器健康檢查
- 文件化新的型別異常錯誤模式
Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。
相關文章


