IRONSOFTWAREHOME
视频

如何在Blazor服务器中使用C#将Razor转换为PDF

Curtis Chau
Curtis Chau
Updated: 2026年7月19日

从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 之上构建的内容。 该形状在生产中有真实的限制:

  1. **运行容器:**您需要运行、监控和更新在应用程序可访问的地方的 kaizenio.azurecr.io/html-to-pdf:latest — 本地 Docker、sidecar 或独立主机。

  2. **没有 .NET SDK:**每个 C# 调用都是手动实现的 HttpClient POST + JSON。 没有IntelliSense,没有请求形状的编译时检查。

  3. **小型 v1.x API 接口:**文档记录的 JSON 请求体仅接受一个 html 字段。 URL-to-PDF,自定义样式表,页眉/页脚,页面大小,方向和边距被列为路线图项目而不是发布的功能 — 除了渲染 HTML 字符串之外的任何内容都必须在 HTML 内部表达,通常通过 @page CSS 和绝对定位的 div。

  4. **不支持页码:**API 没有 {page}/ {total}占位符,因此无法在服务器端生成"第 X 页,共 Y 页"页脚。

  5. **每个 PDF 的 HTTP 往返:**即使容器在 localhost 上运行,每个 PDF 都需要支付 JSON 序列化和网络跳跃的成本。

  6. **免费层的水印:**如果没有在容器上设置 KAIZEN_PDF_LICENSE 环境变量,输出就会有水印。

Kaizen.io 与IronPDF对比

特征Kaizen.io HTML 到 PDFIronPDF
分发Docker 映像 kaizenio.azurecr.io/html-to-pdfNuGet 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 CSSRenderingOptions.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
Text

开始之前

前提条件

  1. .NET环境: .NET Framework 4.6.2+或.NET Core 3.1+ / .NET 5+
  2. **NuGet 访问权限:**能够安装 NuGet 包
  3. **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
SHELL

许可配置

// Add at application startup (Program.cs or Startup.cs)
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" .
SHELL

完整的 API 参考

概念映射

没有需要映射的Kaizen .NET类——只有JSON请求形状和您围绕它构建的约定。

Kaizen.io概念IronPDF 同等产品
HttpClient + POST /html-to-pdfChromePdfRenderer
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'> hackRenderingOptions.TextHeader / HtmlHeader
固定定位的 <div class='footer'> hackRenderingOptions.TextFooter / HtmlFooter
HttpClient.PostAsyncRenderHtmlAsPdfAsync
容器环境变量 KAIZEN_PDF_LICENSEIronPdf.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);
    }
}

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");
    }
}

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());
    }
}

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");
    }
}

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());
    }
}
C#

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");
    }
}

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();

占位符语法

如果您以前在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
C#

删除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);

故障排除

问题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);

问题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;

问题3:页码无法呈现

**问题:**Kaizen v1.x 没有 {page}/ {total}占位符支持,因此任何迁移前的"第 X 页,共 Y 页"页脚要么缺失,要么是静态文本。

解决方案: 使用IronPDF的页眉/页脚占位符:

renderer.RenderingOptions.TextFooter = new TextHeaderFooter
{
    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>");

迁移清单

迁移前

  • 定位每个 Kaizen 调用点(搜索 html-to-pdf, KAIZEN_PDF_LICENSE, kaizenio.azurecr.io, localhost:8080
  • 文档化用于尺寸、方向、边距的内联 @page CSS
  • 文档伪造的页眉/页脚div(固定位置且有负偏移)
  • 列出任何客户端占位符替换 (html.Replace("{page}", ...) 等)
  • 注意容器生命周期:拉取、运行、重启、许可环境变量
  • 获取IronPDF许可证密钥

容器拆解

  • 停止并移除运行中的 Kaizen 容器 (docker stop kaizen-pdf && docker rm kaizen-pdf)
  • 从CI/CD中移除Kaizen的拉取/运行步骤
  • 从 secrets/env 中移除 KAIZEN_PDF_LICENSE
  • 安装 IronPdf NuGet 包 (dotnet add package IronPdf)

代码更改

  • 在启动时添加许可证密钥配置
  • HttpClient POST 替换为 ChromePdfRenderer
  • 将嵌入的 @page CSS 移入 RenderingOptions 属性
  • 将 JSON POST 替换为 RenderHtmlAsPdf() / RenderHtmlFileAsPdf() / RenderUrlAsPdf()
  • 将伪造的页眉/页脚 div 替换为 TextHeader/FooterHtmlHeader/Footer
  • 更新占位符语法 ({total}{total-pages}, {title}{html-title})
  • pdf.BinaryData 替换 byte[] HTTP 请求体
  • 使用 pdf.SaveAs() 代替 File.WriteAllBytes()
  • 删除容器可达性错误处理和重试/后退

测试

  • 测试所有 PDF 生成路径
  • 验证页眉/页脚渲染和页码(新功能)
  • 验证边距、页面大小和方向
  • 测试离线操作(不需要容器)

后迁移

  • 拆解Kaizen容器基础设施
  • 更新环境变量/秘密
  • 从监控/报警中移除容器健康检查
  • 文档记录新的类型化异常错误模式

请注意: Kaizen.io 是其各自所有者的注册商标。 本网站与Kaizen.io无关联,未被其认可或赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。
Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户