如何使用 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
# 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.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"
識別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" .
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 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 Class
Kaizen.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 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 Class
RenderHtmlFileAsPdf() 直接讀取文件,頁面大小和方向從內嵌@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 As New HttpClient()
Dim page As String = Await http.GetStringAsync("https://example.com")
Dim html As String = $"<!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 As String = JsonSerializer.Serialize(New With {Key .html = html})
Dim response As HttpResponseMessage = 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 Class
RenderUrlAsPdf() 直接抓取並渲染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()
佔位符語法
如果您之前將字串手動替換到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
Imports System.IO
' 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);
故障排除
問題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)
問題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
問題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}"
}
如果您之前在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>")
遷移檢查表
遷移前
- 定位每個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容器基礎結構
- 更新環境變數 / 密鑰
- 從監控/警報中刪除容器健康檢查
- 文件化新的型別異常錯誤模式

