如何用 C# 從 Gotenberg 轉移到 IronPDF
從Gotenberg遷移到IronPDF將您的.NET PDF工作流程從基於Docker的微服務架構和HTTP API呼叫轉變為內加工本C#程式庫。 本指南提供了一個全面的逐步遷移路徑,消除了專業.NET開發者的基礎設施開銷、網路延遲和容器管理的複雜性。
為什麼從Gotenberg遷移到IronPDF
Gotenberg架構問題
Gotenberg是一個用於PDF生成的基於Docker的微服務架構。 雖然功能強大且靈活,但對C#應用程式引入了顯著的複雜性:
-
基礎設施開銷:需要Docker、容器編排(Kubernetes/Docker Compose)、服務發現和負載均衡。 每次部署都變得更加複雜。
-
網路延遲:每次PDF操作都需要HTTP呼叫到一個獨立的服務——每個請求額外增加10-100毫秒的延遲。在高並發場景中,這種延遲很快就會積累。
-
冷啟動問題:容器啟動可能會在首次請求中增加2-5秒。 每次pods重啟、每次擴展事件和每次部署都會觸發冷啟動。
-
操作複雜性:您必須管理容器健康狀況、擴展、日誌記錄和監控,這些與您的主要應用程式是分開的問題。
-
多部分表單資料:每個請求需要構造多部分表單資料,有冗長,容易出錯,且維護繁瑣。
-
故障點:網路超時、服務不可用和容器崩潰都成為需要您處理的責任。
- 版本管理:Gotenberg映像獨立於您的應用程式進行更新; API變更可能會意外破壞整合。
Gotenberg與IronPDF比較
| 方面 | Gotenberg | IronPDF |
|---|---|---|
| 部署 | Docker容器 + 編排 | 單個NuGet套件 |
| 架構 | 微服務(REST API) | 內加工本程式庫 |
| 每次請求延遲 | 10-100毫秒以上(網路往返) | < 1毫秒開銷 |
| 冷啟動 | 2-5秒(容器初始化) | 1-2秒(僅首次渲染) |
| 基礎設施 | Docker,Kubernetes,負載均衡器 | 不需要任何基礎設施 |
| 故障模式 | 網路、容器、服務故障 | 標準的.NET異常 |
| API風格 | REST多部分/表單資料 | 內建C#方法呼叫 |
| 擴展 | 水平(更多容器) | 垂直(內處理) |
| 除錯 | 需要分佈式跟踪 | 標準除錯器 |
| 版本控制 | 容器映像標籤 | NuGet套件版本 |
對於以當前.NET版本為目標的團隊而言,IronPDF提供了一個沒有基礎設施依賴的基礎,並能夠自然而然地與現代.NET模式整合。
遷移複雜性評估
功能的預估努力程度
| 功能 | 遷移複雜性 |
|---|---|
| HTML轉PDF | 非常低 |
| URL到PDF | 非常低 |
| 自定紙張尺寸 | 低 |
| 邊距 | 低 |
| PDF合併 | 低 |
| 頁眉/頁腳 | 中 |
| 等待延遲 | 低 |
| PDF/A轉換 | 低 |
範式轉變
這次Gotenberg遷移的基礎轉變是從使用多部分表單資料的HTTP API呼叫到內建C#方法呼叫:
Gotenberg:HTTP POST多部分表單數據到Docker容器
IronPDF:直接使用C#對象的方法呼叫
開始之前
前提條件
- .NET版本: IronPDF支援.NET Framework 4.6.2+和.NET Core 3.1+ / .NET 5/6/7/8/9+
- 授權金鑰:從ironpdf.com取得您的IronPDF授權金鑰
- 計劃移除基礎設施:記錄Gotenberg容器以便在遷移後報廢
識別所有Gotenberg使用情況
# Find direct HTTP calls to Gotenberg
grep -r "gotenberg\|/forms/chromium\|/forms/libreoffice\|/forms/pdfengines" --include="*.cs" .
# Find GotenbergSharpApiClient usage
grep -r "GotenbergSharpClient\|Gotenberg.Sharp\|ChromiumRequest" --include="*.cs" .
# Find Docker/KubernetesGotenbergconfiguration
grep -r "gotenberg/gotenberg\|gotenberg:" --include="*.yml" --include="*.yaml" .
# Find direct HTTP calls to Gotenberg
grep -r "gotenberg\|/forms/chromium\|/forms/libreoffice\|/forms/pdfengines" --include="*.cs" .
# Find GotenbergSharpApiClient usage
grep -r "GotenbergSharpClient\|Gotenberg.Sharp\|ChromiumRequest" --include="*.cs" .
# Find Docker/KubernetesGotenbergconfiguration
grep -r "gotenberg/gotenberg\|gotenberg:" --include="*.yml" --include="*.yaml" .
NuGet包變更
# RemoveGotenbergclient (if using)
dotnet remove package Gotenberg.Sharp.API.Client
# Install IronPDF
dotnet add package IronPdf
# RemoveGotenbergclient (if using)
dotnet remove package Gotenberg.Sharp.API.Client
# Install IronPDF
dotnet add package IronPdf
快速開始遷移
步驟1:更新授權配置
之前(Gotenberg):
Gotenberg不需要授權,但需要Docker基礎設施和容器URL。
private readonly string _gotenbergUrl = "http://localhost:3000";
private readonly string _gotenbergUrl = "http://localhost:3000";
Private ReadOnly _gotenbergUrl As String = "http://localhost:3000"
之後(IronPDF):
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
步驟2:更新名稱空間的引入
// Before (Gotenberg)
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
// Before (Gotenberg)
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Imports IronPdf
Imports IronPdf.Rendering
完整API參考
Gotenberg端點到IronPDF映射
| Gotenberg路徑 | IronPDF等價 |
|---|---|
POST /forms/chromium/convert/html |
ChromePdfRenderer.RenderHtmlAsPdf() |
POST /forms/chromium/convert/url |
ChromePdfRenderer.RenderUrlAsPdf() |
POST /forms/pdfengines/merge |
PdfDocument.Merge() |
POST /forms/pdfengines/convert |
pdf.SaveAs()帶設置 |
GET /health |
無 |
表單參數到RenderingOptions映射
| Gotenberg參數 | IronPDF 屬性 | 轉換說明 |
|---|---|---|
paperWidth(英寸) |
RenderingOptions.PaperSize |
使用枚舉或自定尺寸 |
paperHeight(英寸) |
RenderingOptions.PaperSize |
使用枚舉或自定尺寸 |
marginTop(英寸) |
RenderingOptions.MarginTop |
乘以25.4換算為毫米 |
marginBottom(英寸) |
RenderingOptions.MarginBottom |
乘以25.4換算為毫米 |
printBackground |
RenderingOptions.PrintHtmlBackgrounds |
布林值 |
landscape |
RenderingOptions.PaperOrientation |
Landscape枚舉 |
"3s") |
RenderingOptions.WaitFor.RenderDelay(ms) |
將字串轉換為毫秒 |
程式碼遷移範例
範例1:基本HTML到PDF
之前(Gotenberg):
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergExample
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Hello from Gotenberg</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("output.pdf", pdfBytes);
Console.WriteLine("PDF generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergExample
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Hello from Gotenberg</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("output.pdf", pdfBytes);
Console.WriteLine("PDF generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Module GotenbergExample
Async Function Main() As Task
Dim gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
Dim html = "<html><body><h1>Hello from Gotenberg</h1></body></html>"
content.Add(New StringContent(html), "files", "index.html")
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("output.pdf", pdfBytes)
Console.WriteLine("PDF generated successfully")
End Using
End Using
End Function
End Module
之後(IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfExample
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello from IronPDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfExample
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello from IronPDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully");
}
}
Imports System
Imports IronPdf
Class IronPdfExample
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html = "<html><body><h1>Hello from IronPDF</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF generated successfully")
End Sub
End Class
差異是很顯著的:Gotenberg需要構建一個MultipartFormDataContent,進行一個異步HTTP POST至運行的Docker容器,並處理字節陣列的響應。 IronPDF將此減少為僅需三行程式碼使用ChromePdfRenderer方法呼叫——無網路開銷,無容器依賴,無異步複雜性。 查看HTML到PDF文件以獲取其他渲染選項。
範例2:URL轉PDF轉換
之前(Gotenberg):
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergUrlToPdf
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/url";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
content.Add(new StringContent("https://example.com"), "url");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("webpage.pdf", pdfBytes);
Console.WriteLine("PDF from URL generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergUrlToPdf
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/url";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
content.Add(new StringContent("https://example.com"), "url");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("webpage.pdf", pdfBytes);
Console.WriteLine("PDF from URL generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Module GotenbergUrlToPdf
Async Function Main() As Task
Dim gotenbergUrl As String = "http://localhost:3000/forms/chromium/convert/url"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
content.Add(New StringContent("https://example.com"), "url")
Dim response As HttpResponseMessage = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes As Byte() = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("webpage.pdf", pdfBytes)
Console.WriteLine("PDF from URL generated successfully")
End Using
End Using
End Function
End Module
之後(IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfUrlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfUrlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL generated successfully");
}
}
Imports System
Imports IronPdf
Class IronPdfUrlToPdf
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
Console.WriteLine("PDF from URL generated successfully")
End Sub
End Class
Gotenberg方法需要使用不同的端點(/forms/chromium/convert/url),使用URL作為表單字段構建多部分內容,並處理異步HTTP響應。 IronPDF的PdfDocument物件。 瞭解更多關於URL到PDF轉換。
範例3:自定義紙張尺寸和邊距
之前(Gotenberg):
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergCustomSize
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
content.Add(new StringContent("8.5"), "paperWidth");
content.Add(new StringContent("11"), "paperHeight");
content.Add(new StringContent("0.5"), "marginTop");
content.Add(new StringContent("0.5"), "marginBottom");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes);
Console.WriteLine("Custom size PDF generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergCustomSize
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
content.Add(new StringContent("8.5"), "paperWidth");
content.Add(new StringContent("11"), "paperHeight");
content.Add(new StringContent("0.5"), "marginTop");
content.Add(new StringContent("0.5"), "marginBottom");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes);
Console.WriteLine("Custom size PDF generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Class GotenbergCustomSize
Shared Async Function Main() As Task
Dim gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
Dim html = "<html><body><h1>Custom Size PDF</h1></body></html>"
content.Add(New StringContent(html), "files", "index.html")
content.Add(New StringContent("8.5"), "paperWidth")
content.Add(New StringContent("11"), "paperHeight")
content.Add(New StringContent("0.5"), "marginTop")
content.Add(New StringContent("0.5"), "marginBottom")
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes)
Console.WriteLine("Custom size PDF generated successfully")
End Using
End Using
End Function
End Class
之後(IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class IronPdfCustomSize
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom-size.pdf");
Console.WriteLine("Custom size PDF generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class IronPdfCustomSize
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom-size.pdf");
Console.WriteLine("Custom size PDF generated successfully");
}
}
Imports System
Imports IronPdf
Imports IronPdf.Rendering
Module IronPdfCustomSize
Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
renderer.RenderingOptions.MarginTop = 50
renderer.RenderingOptions.MarginBottom = 50
Dim html As String = "<html><body><h1>Custom Size PDF</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("custom-size.pdf")
Console.WriteLine("Custom size PDF generated successfully")
End Sub
End Module
Gotenberg需要基於字串的參數("0.5")新增到多部分表單資料中——無型別安全,無IntelliSense,容易輸入錯誤。 IronPDF提供具有PdfPaperSize枚舉和數字邊距值的強型別屬性。 請注意IronPDF的邊距單位為毫米(50毫米≈2英寸),而Gotenberg使用英寸。
關鍵遷移注意事項
單位轉換
這次Gotenberg遷移中最重要的轉換是邊距單位:
// Gotenberg: margins in inches
content.Add(new StringContent("0.5"), "marginTop"); // 0.5 inches
content.Add(new StringContent("1"), "marginBottom"); // 1 inch
// IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7; // 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4; // 1 inch × 25.4 = 25.4mm
// Gotenberg: margins in inches
content.Add(new StringContent("0.5"), "marginTop"); // 0.5 inches
content.Add(new StringContent("1"), "marginBottom"); // 1 inch
// IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7; // 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4; // 1 inch × 25.4 = 25.4mm
' Gotenberg: margins in inches
content.Add(New StringContent("0.5"), "marginTop") ' 0.5 inches
content.Add(New StringContent("1"), "marginBottom") ' 1 inch
' IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7 ' 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4 ' 1 inch × 25.4 = 25.4mm
轉換公式:millimeters = inches × 25.4
同步與異步
由於HTTP通信,Gotenberg需要異步操作:
// Gotenberg: Forced async due to network calls
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
// IronPDF: Synchronous in-process execution
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// IronPDF: Async wrapper if needed
var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(html));
// Gotenberg: Forced async due to network calls
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
// IronPDF: Synchronous in-process execution
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// IronPDF: Async wrapper if needed
var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(html));
Imports System.Net.Http
' Gotenberg: Forced async due to network calls
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
' IronPDF: Synchronous in-process execution
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' IronPDF: Async wrapper if needed
Dim pdf = Await Task.Run(Function() renderer.RenderHtmlAsPdf(html))
錯誤處理
// Gotenberg: HTTP error handling
try
{
var response = await client.PostAsync(gotenbergUrl, content);
response.EnsureSuccessStatusCode(); // What if 500? 503? Timeout?
}
catch (HttpRequestException ex) { /* Network error */ }
catch (TaskCanceledException ex) { /* Timeout */ }
// IronPDF: Standard .NET exceptions
try
{
var pdf = renderer.RenderHtmlAsPdf(html);
}
catch (Exception ex)
{
Console.WriteLine($"PDF generation failed: {ex.Message}");
}
// Gotenberg: HTTP error handling
try
{
var response = await client.PostAsync(gotenbergUrl, content);
response.EnsureSuccessStatusCode(); // What if 500? 503? Timeout?
}
catch (HttpRequestException ex) { /* Network error */ }
catch (TaskCanceledException ex) { /* Timeout */ }
// IronPDF: Standard .NET exceptions
try
{
var pdf = renderer.RenderHtmlAsPdf(html);
}
catch (Exception ex)
{
Console.WriteLine($"PDF generation failed: {ex.Message}");
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
' Gotenberg: HTTP error handling
Try
Dim response = Await client.PostAsync(gotenbergUrl, content)
response.EnsureSuccessStatusCode() ' What if 500? 503? Timeout?
Catch ex As HttpRequestException
' Network error
Catch ex As TaskCanceledException
' Timeout
End Try
' IronPDF: Standard .NET exceptions
Try
Dim pdf = renderer.RenderHtmlAsPdf(html)
Catch ex As Exception
Console.WriteLine($"PDF generation failed: {ex.Message}")
End Try
移除基礎設施
遷移後,從您的基礎設施中移除Gotenberg:
# REMOVE from docker-compose.yml:
# services:
# gotenberg:
# image: gotenberg/gotenberg:8
# ports:
# - "3000:3000"
# deploy:
# resources:
# limits:
# memory: 2G
# REMOVE from docker-compose.yml:
# services:
# gotenberg:
# image: gotenberg/gotenberg:8
# ports:
# - "3000:3000"
# deploy:
# resources:
# limits:
# memory: 2G
效能考量
延遲比較
| 操作 | Gotenberg(熱) | Gotenberg(冷啟動) | IronPDF(首次渲染) | IronPDF(後續渲染) |
|---|---|---|---|---|
| 簡單的HTML | 150-300毫秒 | 2-5秒 | 1-2秒 | 50-150毫秒 |
| 複雜的HTML | 500-1500毫秒 | 3-7秒 | 1.5-3秒 | 200-800毫秒 |
| URL渲染 | 1-5秒 | 3-10秒 | 1-5秒 | 500毫秒-3秒 |
消除基礎設施成本
| 資源 | Gotenberg | IronPDF |
|---|---|---|
| 需要的容器 | 1到N(擴展) | 0 |
| 每個容器的記憶體 | 512MB到2GB | 無 |
| 每個請求的網路開銷 | 10-100毫秒 | 0毫秒 |
| 健康檢查端點 | 必需的 | 不需要 |
| 負載均衡器 | 通常需要 | 不需要 |
故障排除
問題1:不需要HttpClient模式
問題:程式碼仍在使用MultipartFormDataContent。
解決方案:完全替換為ChromePdfRenderer:
// Remove all of this:
// using var client = new HttpClient();
// using var content = new MultipartFormDataContent();
// content.Add(new StringContent(html), "files", "index.html");
// var response = await client.PostAsync(url, content);
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all of this:
// using var client = new HttpClient();
// using var content = new MultipartFormDataContent();
// content.Add(new StringContent(html), "files", "index.html");
// var response = await client.PostAsync(url, content);
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
問題2:邊距單位錯誤
問題:遷移後PDF的邊距不正確。
解決方案:將英寸轉換為毫米:
//Gotenbergused inches: "0.5"
//IronPDFuses millimeters: 0.5 × 25.4 = 12.7
renderer.RenderingOptions.MarginTop = 12.7;
//Gotenbergused inches: "0.5"
//IronPDFuses millimeters: 0.5 × 25.4 = 12.7
renderer.RenderingOptions.MarginTop = 12.7;
問題3:容器URL引用
問題:程式碼包含http://gotenberg:3000或類似的URL。
解決方案:移除所有容器URL引用——IronPDF在內部運行:
// Remove:
// private readonly string _gotenbergUrl = "http://gotenberg:3000";
//IronPDFneeds no URL - it's in-process
var renderer = new ChromePdfRenderer();
// Remove:
// private readonly string _gotenbergUrl = "http://gotenberg:3000";
//IronPDFneeds no URL - it's in-process
var renderer = new ChromePdfRenderer();
遷移檢查表
遷移前
- 列出程式碼庫中所有Gotenberg HTTP呼叫
- 記錄當前的Gotenberg配置(超時設置,邊距,紙張尺寸)
- 識別所有Docker/Kubernetes的Gotenberg配置
- 獲得IronPDF授權金鑰
- 計劃基礎設施撤役
程式碼遷移
- 安裝IronPDF的NuGet套件:
dotnet add package IronPdf - 移除Gotenberg客戶端套件
- 將所有HTTP呼叫替換為IronPDF的方法呼叫
- 將邊距單位從英寸轉換為毫米
- 更新錯誤處理(HTTP錯誤→.NET異常)
- 在啟動時新增授權金鑰初始化
基礎設施遷移
- 從Docker Compose / Kubernetes中移除Gotenberg
- 更新CI/CD管道(移除Gotenberg映像拉取)
- 移除Gotenberg的健康檢查
- 從配置中移除Gotenberg URL
測試
- 測試 HTML 到 PDF 的轉換
- 測試 URL 到 PDF 的轉換
- 驗證邊距和尺寸的準確性
- 在負載下進行性能測試
- 測試首次渲染的加熱時間
遷移後
- 移除Gotenberg容器部署
- 將Gotenberg配置文件存檔
- 更新文件
- 監控應用程式的記憶體使用
- 確認沒有孤立的網路連接

