如何在Blazor服务器中使用C#将Razor转换为PDF
从Kaizen.io HTML-to-PDF迁移到IronPDF,用一个通过HTTP暴露的自托管Docker容器替换为一个内嵌的.NET库。Kaizen.io HTML 到 PDF仅作为 Docker 映像 kaizenio.azurecr.io/html-to-pdf 提供,并在端口 8080 上暴露一个 REST 端点 POST /html-to-pdf — 没有官方 .NET SDK 或 NuGet 包,因此每个 C# 调用都必须针对正在运行的容器进行手动实现 HttpClient。 本指南介绍了用IronPDF的 ChromePdfRenderer 替换该模式。
为什么要从 Kaizen.io 迁移到 IronPDF.
容器-API挑战
Kaizen.io HTML-to-PDF 是一个 Docker 容器,拥有一个特意保持小规模的 v1.x API,而 C# 集成方式是基于您自己在 HttpClient 之上构建的内容。 该形状在生产中有真实的限制:
-
运行容器:您需要运行、监控和更新在应用程序可访问的地方的
kaizenio.azurecr.io/html-to-pdf:latest— 本地 Docker、sidecar 或独立主机。 -
没有 .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 序列化和网络跳跃的成本。 - 免费层的水印:如果没有在容器上设置
KAIZEN_PDF_LICENSE环境变量,输出就会有水印。
Kaizen.io 与IronPDF对比
| 特征 | Kaizen.io HTML 到 PDF | IronPDF |
|---|---|---|
| 分发 | Docker 映像 kaizenio.azurecr.io/html-to-pdf |
NuGet IronPdf |
| C#集成 | 手动实现的 HttpClient POST (没有 SDK) |
强类型的 ChromePdfRenderer API |
| 进程模型 | 进程外容器 | 翻译中 |
| 端点界面 (v1.x) | POST /html-to-pdf with { "html": ... } |
HTML、文件、URL的方法 |
| URL输入 | 路线图 | RenderUrlAsPdf(url) |
| 页眉/页脚 | 不在v1.x API中; 通过固定位置CSS伪造 | TextHeader/Footer and HtmlHeader/Footer |
| 页码 | 不支持 | {page}and {total-pages}placeholders |
| 页面大小/方向 | 在 HTML 中嵌入 @page CSS |
RenderingOptions.PaperSize 等。 |
| 许可 | 一次性许可证; 带水印的免费层 | 商业(年度或永久) |
对于标准化现代.NET的团队,IronPDF从请求路径中移除边车容器和HTTP跳,暴露强类型的配置界面。
迁移复杂性评估
按功能估算的工作量
| 特征 | 迁移复杂性 |
|---|---|
| 基本 HTML 到 PDF | 极低 |
| HTML 文件到 PDF | 极低 |
| URL 至 PDF | 低(Kaizen v1.x没有URL端点——解决方案整体替换) |
| 页眉/页脚 | 中(伪CSS divs替换为真实的页眉区域) |
| 页码 | 新功能(在Kaizen v1.x中不可用) |
| 页面设置 | 低 (@page CSS moves to RenderingOptions) |
范式转换
基本的转变是从到Docker容器的进程外HTTP调用到进程内渲染:
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'> hack |
RenderingOptions.TextHeader / HtmlHeader |
固定定位的 <div class='footer'> hack |
RenderingOptions.TextFooter / HtmlFooter |
HttpClient.PostAsync |
RenderHtmlAsPdfAsync |
容器环境变量 KAIZEN_PDF_LICENSE |
IronPdf.License.LicenseKey |
HTTP byte[] 响应 |
pdf.BinaryData / pdf.SaveAs(path) |
占位符映射
Kaizen v1.x没有服务器端占位符。 如果您以前在POST之前手动替换HTML中的字符串,请切换到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——将JSON POST到容器):
// 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
After (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,将其发布到容器的REST端点,检查状态码,将响应读取为字节,并将这些字节写入磁盘。IronPDF的 ChromePdfRenderer 在进程内运行 — RenderHtmlAsPdf() 返回一个带有 PdfDocument 方法的 SaveAs(),因此往返和手动字节管理消失了。 有关其他渲染选项,请参阅 HTML to 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
After (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
After (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 区域替换。 页码通过 {page}和 {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()
占位符语法
如果您以前在POST之前手动替换HTML中的字符串,请切换到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。
解决方案:迁移是从 HttpClient POSTs 针对容器到 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}"
}
如果您之前在自己代码中手动替换了 {total}并在发送POST请求之前,请移除该替换 —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 调用点(搜索
html-to-pdf,KAIZEN_PDF_LICENSE,kaizenio.azurecr.io,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 替换为ChromePdfRenderer - 将嵌入的
@pageCSS 移入RenderingOptions属性 - 将 JSON POST 替换为
RenderHtmlAsPdf()/RenderHtmlFileAsPdf()/RenderUrlAsPdf() - 将伪造的页眉/页脚 div 替换为
TextHeader/Footer或HtmlHeader/Footer - 更新占位符语法 (
{total}→{total-pages},{title}→{html-title}) - 用
pdf.BinaryData替换byte[]HTTP 请求体 - 使用
pdf.SaveAs()代替File.WriteAllBytes() - 删除容器可达性错误处理和重试/后退
测试
- 测试所有 PDF 生成路径
- 验证页眉/页脚渲染和页码(新功能)
- 验证边距、页面大小和方向
- 测试离线操作(不需要容器)
后迁移
- 拆解Kaizen容器基础设施
- 更新环境变量/秘密
- 从监控/报警中移除容器健康检查
- 文档记录新的类型化异常错误模式

