Gotenberg 与 IronPDF:技术比较指南
高登堡vs IronPDF:Docker 微服务 vs 进程内 .NET 库。
当 .NET 开发人员评估 PDF 生成解决方案时,Gotenberg 作为基于 Docker 的微服务出现,它通过 REST API 调用将 HTML 转换为 PDF。 虽然高登堡对于多语言架构来说非常灵活,但它会带来大量的基础设施开销--Docker 容器、网络延迟和操作复杂性。 IronPdf 提供了一种不同的方法:一个进程中的 NuGet 包,提供同样基于 Chromium 的渲染,无需容器、网络调用或基础架构管理。
本比较从技术相关维度对两种解决方案进行了审查,以帮助专业开发人员和架构师针对其 .NET PDF 需求做出明智的决定。
了解哥登堡
Gotenberg 是一种基于 Docker 的 PDF 生成微服务架构。 它作为一个单独的容器运行,可提供 REST API 端点,用于将 HTML、URL 和其他格式转换为 PDF。 每个 PDF 操作都需要对高登堡服务进行 HTTP 调用。
Gotenberg 使用<代码>POST /forms/chromium/convert/html</ 代码等端点实现 HTML 到 PDF 的转换,使用POST /forms/chromium/convert/url实现 URL 到 PDF 的转换。 配置通过多art/form-data 传递,参数基于字符串,如 paperWidth、paperHeight、marginTop 和 marginBottom(单位:英寸)。 该服务需要 Docker 部署、容器编排(Kubernetes/Docker Compose)和网络基础设施。
架构要求
- Docker 容器部署和管理
- 每个 PDF 请求的网络通信(10-100 毫秒以上的延迟)
- 容器冷启动处理(首次请求 2-5 秒)
- 健康检查端点和服务监控
- 为每个请求提供多格式/表单数据结构
了解IronPDF
IronPDF 是一个本地 .NET 库,作为一个 NuGet 包在进程中运行。 它提供基于 Chromium 的 HTML 渲染,无需外部服务、网络调用或容器基础架构。
IronPDF 使用 ChromePdfRenderer 作为其主要的渲染类,并使用 RenderHtmlAsPdf() 和 RenderUrlAsPdf() 等方法。 配置使用 RenderingOptions 上的类型化 C# 属性,包括 PaperSize, MarginTop, MarginBottom (单位:毫米)。 文档使用 SaveAs() 保存,或以 BinaryData 的形式访问。
该库只需要
- NuGet 软件包安装(
dotnet 添加软件包 IronPdf</code) - 许可证密钥配置
- 标准 .NET 项目设置
架构和基础架构比较
这些解决方案的根本区别在于其部署和运行时架构。
| 因素 | 高登堡 | IronPDF |
|---|---|---|
| 部署 | Docker 容器 + 协调 | 单个 NuGet 软件包 |
| 架构 | 微服务(REST API) | 在建库 |
| 每次请求的延迟时间 | 10-100ms+(网络往返) | < 1ms 开销 |
| 冷启动 | 2-5 秒(容器启动) | 1-2 秒(仅限首次呈现) |
| 基础设施 | Docker、Kubernetes、负载平衡器 | 无要求 |
| 网络依赖性 | 要求 | 无 |
| 失败模式 | 网络、容器、服务故障 | .NET 标准例外情况 |
| API 风格 | REST 多art/表单数据 | 本地 C# 方法调用 |
| 扩展 | 横向(更多容器) | 纵向(处理中) |
| 调试 | 分布式跟踪 | 标准调试器 |
| 内存管理 | 独立容器(512MB-2GB) | 共享应用程序内存 |
| 版本控制 | 容器图像标签 | NuGet 软件包版本 |
| 健康检查 | 所需的 HTTP 端点 | 不需要(处理中) |
| CI/CD复杂性 | 容器构建、注册表推送 | 标准 .NET 构建 |
Gotenberg 基于 Docker 的方法需要容器部署、健康监控和网络基础设施管理。IronPDF通过在进程中运行,完全消除了这一基础架构层。
代码比较:常见的 PDF 操作
基本 HTML 到 PDF 的转换
最基本的操作清楚地展示了架构上的差异。
戈登堡:
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");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comIronPDF:
// 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");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comGotenberg 要求创建一个 HttpClient ,构建 MultipartFormDataContent ,将 HTML 添加为具有特定文件名(index.html)的文件附件,向高登堡服务端点进行异步 HTTP POST,读取响应字节并写入磁盘。 每个请求都要通过网络,并伴有延迟和故障模式。
IronPDF 创建一个 ChromePdfRenderer 文件,使用 HTML 字符串调用 RenderHtmlAsPdf() 并使用 SaveAs() 保存。 操作是同步的、进程中的,并使用类型化方法而不是基于字符串的表单数据。
有关高级 HTML 渲染选项,请浏览 HTML 到 PDF 转换指南。
URL到PDF转换
将实时网页转换为 PDF 显示了类似的架构模式。
戈登堡:
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");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comIronPDF:
// 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");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comGotenberg 使用 /forms/chromium/convert/url 端点,并将 URL 作为表单数据传递。IronPDF使用 URL 字符串直接调用 RenderUrlAsPdf() - 一个方法调用取代了 HTTP 基础架构。
自定义页面大小和页边距
配置处理揭示了 API 的设计差异。
戈登堡:
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");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comIronPDF:
// 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");
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comGotenberg 使用基于字符串的参数("8.5", "11", "0.5")添加到多部分表单数据中。 纸张尺寸以英寸为单位。 每个参数都是一个单独的 Add() 调用,没有类型检查或 IntelliSense 支持。
IronPDF 在 RenderingOptions 上使用类型化属性。 PaperSize 接受一个枚举(PdfPaperSize.Letter),页边距是以毫米为单位的数值。 类型化 API 提供编译时检查和 IDE 支持。
在 IronPDF 教程中了解有关渲染配置的更多信息。
API 映射参考
对于正在评估高登堡迁移或比较功能的开发人员,本映射说明了等价操作:
端点到方法映射
| 哥登堡路线 | IronPdf 同等产品 | 备注 |
|---|---|---|
| <代码>POST /forms/chromium/convert/html</ 代码 | <代码>ChromePdfRenderer.RenderHtmlAsPdf()</代码 | HTML 字符串到 PDF |
POST /forms/chromium/convert/url | <代码>ChromePdfRenderer.RenderUrlAsPdf()</代码 | URL 至 PDF |
POST /forms/chromium/convert/markdown</ 代码 | 先将 Markdown 渲染为 HTML | 使用 Markdig 库 |
POST /forms/pdfengines/merge</ 代码 | <代码>PdfDocument.Merge()</代码 | 合并多个 PDF |
POST /forms/pdfengines/metadata/read | <代码>pdf.MetaData</代码 | 阅读元数据 |
POST /forms/pdfengines/metadata/write</ 代码 | <代码>pdf.MetaData.Author = "..."</ 代码 | 编写元数据 |
| <代码>获取 /health</ 代码 | 不适用 | 无需外部服务 |
表单参数到渲染选项映射
| 高登贝格参数 | IronPdf 属性 | 转换注意事项 |
|---|---|---|
| <代码>纸张宽度</代码>(英寸) | <代码>RenderingOptions.SetCustomPaperSizeInInches()</代码 | 自定义使用方法 |
| <代码>纸张高度</代码>(英寸) | <代码>RenderingOptions.SetCustomPaperSizeInInches()</代码 | 自定义使用方法 |
| <代码>marginTop</代码>(英寸) | <代码>RenderingOptions.MarginTop</代码 | 毫米数乘以 25.4 |
| <代码>marginBottom</代码>(英寸) | <代码>RenderingOptions.MarginBottom</代码 | 毫米数乘以 25.4 |
| <代码>marginLeft</代码>(英寸) | <代码>RenderingOptions.MarginLeft</代码 | 毫米数乘以 25.4 |
| <代码>marginRight</代码>(英寸) | <代码>RenderingOptions.MarginRight</代码 | 毫米数乘以 25.4 |
| <代码>打印背景</代码 | <代码>RenderingOptions.PrintHtmlBackgrounds</代码 | 布尔 |
| <代码>景观</代码 | <代码>RenderingOptions.PaperOrientation</代码 | Landscape 枚举 |
scale | <代码>RenderingOptions.Zoom</代码 | 百分比(100 = 1.0) |
| <代码>waitDelay</代码 | <代码>RenderingOptions.RenderDelay</代码 | 转换为毫秒 |
| <代码>emulatedMediaType</代码 | <代码>RenderingOptions.CssMediaType</代码 | <代码>屏幕</代码>或 <代码>打印</代码 |
注意单位换算:Gotenberg 使用英寸表示页边距(例如,"0.5" = 0.5 英寸 = 12.7 毫米),而IronPDF使用毫米。
基础架构比较
高登堡Docker Compose
Gotenberg 需要容器基础设施:
#高登堡requires container management
version: '3.8'
services:
app:
depends_on:
- gotenberg
environment:
- GOTENBERG_URL=http://gotenberg:3000
gotenberg:
image: gotenberg/gotenberg:8
ports:
- "3000:3000"
deploy:
resources:
limits:
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s#高登堡requires container management
version: '3.8'
services:
app:
depends_on:
- gotenberg
environment:
- GOTENBERG_URL=http://gotenberg:3000
gotenberg:
image: gotenberg/gotenberg:8
ports:
- "3000:3000"
deploy:
resources:
limits:
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30sIronPDF配置
IronPdf 无需额外服务:
#IronPDF- No additional services needed
version: '3.8'
services:
app:
environment:
- IRONPDF_LICENSE_KEY=${IRONPDF_LICENSE_KEY}
# No高登堡service. No health checks. No resource limits.#IronPDF- No additional services needed
version: '3.8'
services:
app:
environment:
- IRONPDF_LICENSE_KEY=${IRONPDF_LICENSE_KEY}
# No高登堡service. No health checks. No resource limits.基础设施差异很大:Gotenberg 需要容器部署、健康监控、资源分配和服务依赖性。 IronPdf 与应用程序一起在进程中运行。
性能特点
| 手术 | 哥登堡(温暖的集装箱) | 高登堡(冷启动) | IronPdf (初渲染) | IronPdf (后续) |
|---|---|---|---|---|
| 简单的 HTML | 150-300 毫秒 | 2-5 秒 | 1-2 秒 | 50-150ms |
| 复杂的 HTML | 500-1500ms | 3-7 秒 | 1.5-3 秒 | 200-800ms |
| URL 渲染 | 1-5 秒 | 3-10 秒 | 1-5 秒 | 500ms-3s |
| PDF 合并 | 200-500 毫秒 | 2-5 秒 | 100-300 毫秒 | 100-300 毫秒 |
Gotenberg 的网络往返每次请求会增加 10-100ms+ 的时间。容器冷启动会增加 2-5 秒。IronPDF的首次渲染会产生 Chromium 初始化(1-2 秒),但后续渲染的开销极小。
团队何时考虑从高登堡迁移到 IronPDF?
开发团队评估从高登堡向IronPDF过渡的原因有以下几点:
基础设施开销:Gotenberg 需要使用 Docker、容器协调(Kubernetes/Docker Compose)、服务发现和负载平衡。 寻求更简单部署的团队发现IronPDF的 NuGet 方法消除了这些基础架构方面的顾虑。
网络延迟:每个高登堡PDF 操作都需要向单独的服务进行 HTTP 调用,每次请求会增加 10-100ms+ 的时间。对于大容量应用程序,这种开销会不断累积。IronPDF的进程内方法在初始化后的开销可以忽略不计。
冷启动问题:容器启动会使首次请求时间延长 2-5 秒。 即使是温暖的容器也有网络开销。 每次 pod 重启、扩展事件或部署都会触发冷启动。IronPDF的冷启动在每个应用程序生命周期内发生一次。
操作复杂性:Gotenberg 要求将容器健康、扩展、日志和监控作为单独的关注点进行管理。 网络超时、服务不可用和容器崩溃成为应用程序关注的问题。 IronPdf 使用标准的 .NET 异常处理。
多部分表单数据 API:每个高登堡请求都需要使用基于字符串的参数构建多部分/表单数据有效载荷--语句冗长且不进行编译时类型检查。IronPDF提供类型化的 C# 属性,并支持 IntelliSense。
版本管理:Gotenberg 图像与您的应用程序分开更新。 API 的更改可能会破坏集成。IronPDF版本通过 NuGet 与标准 .NET 依赖关系管理进行管理。
优势和考虑因素
高登堡的优势
- Polyglot 架构:适用于任何可以进行 HTTP 调用的语言
- 语言无关性:与 .NET 生态系统无关
- MIT 许可证:免费开源
- 微服务模式:适合容器化架构
戈登堡注意事项
- 基础设施开销:需要使用 Docker、Kubernetes 和负载平衡器
- 网络延迟:每次请求 10-100ms+
- 冷启动:2-5 秒容器初始化
- 基于字符串的 API:无类型安全或 IntelliSense
- 分布式调试:需要分布式跟踪
- 健康监控:需要管理的其他端点
IronPDF的优势
IronPDF注意事项
- .NET专用:专为 .NET 生态系统设计
- 商业许可:生产使用要求
结论
Gotenberg 和IronPDF代表了在 .NET 应用程序中生成 PDF 的根本不同方法。高登堡基于 Docker 的微服务架构引入了容器管理、网络延迟和操作复杂性。 每个 PDF 操作都需要 HTTP 通信以及相关的故障模式和冷启动惩罚。
IronPDF 提供与进程内库一样的基于 Chromium 的渲染。 NuGet 软件包取消了 Docker 容器、网络调用和基础设施管理。 类型化的 C# API 取代了基于字符串的多部分表单数据。 标准的 .NET 异常处理取代了 HTTP 状态代码和网络故障模式。
随着企业对 .NET 10、C# 14 以及 2026 年之前的应用程序开发进行规划,在微服务基础架构开销和进程内库简易性之间做出选择会极大地影响部署和操作的复杂性。 寻求在保持 HTML/CSS/JavaScript 渲染保真度的同时减轻基础架构负担的团队会发现 IronPdf 能有效满足这些要求。