跳至頁尾內容
影片

如何使用 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上構建的。 這種形態在生產中有實際的限制:

  1. 容器運作: 您需要運行、監控和更新kaizenio.azurecr.io/html-to-pdf:latest,它必須在應用程式可以存取的某個地方 —— 本地Docker、側車或獨立主機。

  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序列化和socket跳的代價。

  6. 免費層上的浮水印: 如果容器上未設置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/FooterHtmlHeader/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

開始之前

前提條件

  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
# 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";
// 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"
$vbLabelText   $csharpLabel

識別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" .
SHELL

完整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
$vbLabelText   $csharpLabel

之後(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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

之後(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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

之後(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
$vbLabelText   $csharpLabel

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()
$vbLabelText   $csharpLabel

佔位符語法

如果您之前將字串手動替換到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
$vbLabelText   $csharpLabel

刪除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);
$vbLabelText   $csharpLabel

故障排除

問題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)
$vbLabelText   $csharpLabel

問題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
$vbLabelText   $csharpLabel

問題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}"
}
$vbLabelText   $csharpLabel

如果您之前在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>")
$vbLabelText   $csharpLabel

遷移檢查表

遷移前

  • 定位每個Kaizen調用點(搜尋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
  • 將嵌入的@page CSS移入RenderingOptions屬性
  • RenderHtmlAsPdf() / RenderHtmlFileAsPdf() / RenderUrlAsPdf()替換JSON POST
  • HtmlHeader/Footer替換虛假頁眉/頁腳div
  • 更新佔位符語法({total}{title}{html-title}
  • byte[] HTTP主體
  • 使用File.WriteAllBytes()
  • 刪除容器可達性錯誤處理和重試/退避

測試

  • 測試所有PDF生成流程
  • 驗證頁眉/頁腳的呈現和頁碼(新功能)
  • 驗證邊距、頁面大小和方向
  • 測試脫機操作(不需要容器)

遷移後

  • 拆除Kaizen容器基礎結構
  • 更新環境變數 / 密鑰
  • 從監控/警報中刪除容器健康檢查
  • 文件化新的型別異常錯誤模式

請注意Kaizen.io是其相應所有者的註冊商標。 本網站與Kaizen.io沒有關聯,不由其認可或贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供參考,反映撰寫時公開可用的資訊。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話