
如何在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
许可配置
// 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'> 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 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 ModuleAfter (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,将其发布到容器的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 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 ModuleAfter (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 ModuleAfter (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 区域替换。 页码通过 {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()' 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' 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。
解决方案:迁移是从 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)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}"
}如果您之前在自己代码中手动替换了 {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>")' 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容器基础设施
- 更新环境变量/秘密
- 从监控/报警中移除容器健康检查
- 文档记录新的类型化异常错误模式
Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。
相关文章


