如何用 C# 从 CraftMyPDF 迁移到 IronPDF
为什么要从CraftMyPDF迁移到 IronPDF?
基于云的 PDF API(如 CraftMyPDF)引入了一些基本问题,使其不适合许多生产环境。
基于云的 PDF API 的问题
1.您的数据离开您的系统:每个 HTML 模板和 JSON 数据有效负载都会传输到CraftMyPDF的服务器。 对于发票、合同、医疗记录或任何敏感的商业数据,这会产生 HIPAA、GDPR 和 SOC2 合规风险。
2.网络延迟:CraftMyPDF自己的文档指出,每个 PDF 需要 1.5-30 秒。IronPDF可在几毫秒内本地生成。
3.每个 PDF 的成本累积起来:每月 10,000 个 PDF 按订阅费率计算会产生大量的经常性成本,而一次性永久许可则不然。
4.针对打印优化的输出:云 API 通常会针对打印进行优化——减少背景并简化颜色以节省"墨水"。因此,最终输出结果与屏幕上显示的 HTML 代码看起来截然不同。
5.模板锁定:CraftMyPDF需要使用其专有的拖放式编辑器。 不能随意使用标准 HTML/CSS。
架构比较
| 方面 | CraftMyPDF | IronPDF |
|---|---|---|
| 数据位置 | 云(您的数据离开您的系统) | 内部部署(数据永不丢失) |
| 延迟 | 1.每个 PDF 文件 5-30 秒 | 毫秒 |
| 定价 | 按 PDF 订阅 | 一次性永久许可 |
| 模板系统 | 仅限专有的拖放功能 | 任何 HTML/CSS/JavaScript |
| 输出质量 | 印刷优化 | 像素完美的屏幕渲染 |
| 离线工作 | 否(需要互联网) | 是 |
| 合规性 | 数据叶组织 | 符合 SOC2/HIPAA 标准 |
功能对比
| 特征 | CraftMyPDF | IronPDF |
|---|---|---|
| HTML 至 PDF | 通过 API 模板 | ✅ 本地 |
| URL 至 PDF | 通过 API | ✅ 本地 |
| 自定义模板 | 仅限专有编辑器 | ✅ 任何 HTML |
| 支持 CSS3 | 有限的 | ✅ 全文 |
| JavaScript 渲染 | 有限的 | ✅ 全文 |
| 合并/拆分 PDF | 通过 API | ✅ 本地 |
| 水印 | 通过 API | ✅ 本地 |
| 离线工作 | ❌ | ✅ |
| 自托管 | ❌ | ✅ |
迁移前准备
前提条件
确保您的环境符合这些要求:
- .NET Framework 4.6.2+ 或 .NET Core 3.1 / .NET 5-9
- Visual Studio 2019+ 或带有 C# 扩展的 VS Code
- 访问 NuGet 包管理器 -IronPDF许可证密钥(可在ironpdf.com免费试用)
审核CraftMyPDF的使用情况
在解决方案目录中运行这些命令,以识别所有CraftMyPDF引用:
# Find allCraftMyPDFusages in your codebase
grep -r "CraftMyPdf\|craftmypdf\|api.craftmypdf.com" --include="*.cs" .
grep -r "X-API-KEY" --include="*.cs" .
# Find API key references
grep -r "your-api-key\|template-id\|template_id" --include="*.cs" .
# Find NuGet package references
grep -r "CraftMyPdf\|RestSharp" --include="*.csproj" .
# Find allCraftMyPDFusages in your codebase
grep -r "CraftMyPdf\|craftmypdf\|api.craftmypdf.com" --include="*.cs" .
grep -r "X-API-KEY" --include="*.cs" .
# Find API key references
grep -r "your-api-key\|template-id\|template_id" --include="*.cs" .
# Find NuGet package references
grep -r "CraftMyPdf\|RestSharp" --include="*.csproj" .
值得期待的重大变化
| 变更 | CraftMyPDF | IronPDF | 影响 |
|---|---|---|---|
| 架构 | 云 REST API | 本地 .NET 库 | 删除 HTTP 调用 |
| 模板 | 专有编辑器 | 标准 HTML | 将模板转换为 HTML |
| API关键字 | 每次通话都需要 | 启动时的许可 | 删除 API 密钥处理 |
| 同步模式 | 要求 (HTTP) | 可选项 | 如果愿意,请删除等待 |
| 错误处理 | HTTP 状态代码 | 例外情况 | 更改 try/catch 模式 |
| 数据绑定 | JSON 模板 | 字符串插值 | 简化数据绑定 |
逐步迁移过程
步骤 1:更新 NuGet 软件包
移除 HTTP 客户端库并安装 IronPDF:
# Remove RestSharp HTTP client
dotnet remove package RestSharp
# Install IronPDF
dotnet add package IronPdf
# Remove RestSharp HTTP client
dotnet remove package RestSharp
# Install IronPDF
dotnet add package IronPdf
步骤 2:更新命名空间引用
用IronPDF替换 HTTP 客户端命名空间:
// Remove these
using RestSharp;
using System.IO;
// Add this
using IronPdf;
// Remove these
using RestSharp;
using System.IO;
// Add this
using IronPdf;
Imports IronPdf
步骤 3:配置许可证(启动时一次)
用单个许可证配置替换每次请求的 API 密钥头:
// Add at application startup (Program.cs or Global.asax)
// This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Global.asax)
// This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Global.asax)
' This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
完整的 API 迁移参考
API 端点映射
| CraftMyPDF | IronPDF |
|---|---|
POST /v1/create |
renderer.RenderHtmlAsPdf(html) |
X-API-KEY 标头 |
License.LicenseKey = "..." |
template_id |
标准 HTML 字符串 |
{%name%}占位符 |
$"{name}" C# 插值 |
POST /v1/merge |
PdfDocument.Merge(pdfs) |
POST /v1/add-watermark |
pdf.ApplyWatermark(html) |
| Webhook 回调 | 不需要 |
| 费率限制 | 不适用 |
配置映射
| CraftMyPDF 选项 | IronPDF 同等产品 |
|---|---|
template_id |
HTML 字符串 |
data JSON |
C# 插值 |
page_size: "A4" |
PaperSize = PdfPaperSize.A4 |
orientation: "landscape" |
PaperOrientation = Landscape |
margin_top: 20 |
MarginTop = 20 |
header |
HtmlHeader |
footer |
HtmlFooter |
代码迁移示例
HTML 到 PDF 转换
最常见的操作演示了从云 API 到本地渲染的基本架构转变。
CraftMyPDF实现:
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("output.pdf", response.RawBytes);
}
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("output.pdf", response.RawBytes);
}
}
Imports System
Imports RestSharp
Imports System.IO
Module Program
Sub Main()
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
request.AddJsonBody(New With {
.template_id = "your-template-id",
.data = New With {
.html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
}
})
Dim response = client.Execute(request)
File.WriteAllBytes("output.pdf", response.RawBytes)
End Sub
End Module
IronPDF 实现:
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>");
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>");
pdf.SaveAs("output.pdf");
}
}
Imports System
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>")
pdf.SaveAs("output.pdf")
End Sub
End Class
IronPDF 省去了 RestClient 设置、API key headers、模板 ID 和 HTTP 响应处理--将 15 行云操作减少到 4 行本地代码。 有关更多选项,请参阅 HTML 转 PDF 文档。
URL到PDF转换
CraftMyPDF实现:
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
url = "https://example.com"
},
export_type = "pdf"
});
var response = client.Execute(request);
File.WriteAllBytes("webpage.pdf", response.RawBytes);
}
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
url = "https://example.com"
},
export_type = "pdf"
});
var response = client.Execute(request);
File.WriteAllBytes("webpage.pdf", response.RawBytes);
}
}
Imports System
Imports RestSharp
Imports System.IO
Module Program
Sub Main()
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
request.AddJsonBody(New With {
.template_id = "your-template-id",
.data = New With {
.url = "https://example.com"
},
.export_type = "pdf"
})
Dim response = client.Execute(request)
File.WriteAllBytes("webpage.pdf", response.RawBytes)
End Sub
End Module
IronPDF 实现:
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports System
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
IronPDF 的 RenderUrlAsPdf 方法可以捕获完整的网页,包括 JavaScript 渲染的内容。 有关更多选项,请参阅 URL to PDF 文档。
页眉和页脚
CraftMyPDF实现:
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Document Content</h1>",
header = "<div>Page Header</div>",
footer = "<div>Page {page} of {total_pages}</div>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("document.pdf", response.RawBytes);
}
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Document Content</h1>",
header = "<div>Page Header</div>",
footer = "<div>Page {page} of {total_pages}</div>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("document.pdf", response.RawBytes);
}
}
Imports System
Imports RestSharp
Imports System.IO
Module Program
Sub Main()
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
request.AddJsonBody(New With {
.template_id = "your-template-id",
.data = New With {
.html = "<h1>Document Content</h1>",
.header = "<div>Page Header</div>",
.footer = "<div>Page {page} of {total_pages}</div>"
}
})
Dim response = client.Execute(request)
File.WriteAllBytes("document.pdf", response.RawBytes)
End Sub
End Module
IronPDF 实现:
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}"
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("document.pdf");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}"
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("document.pdf");
}
}
Imports System
Imports IronPdf
Imports IronPdf.Rendering
Module Program
Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
.CenterText = "Page Header"
}
renderer.RenderingOptions.TextFooter = New TextHeaderFooter() With {
.CenterText = "Page {page} of {total-pages}"
}
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>")
pdf.SaveAs("document.pdf")
End Sub
End Module
IronPDF 支持像 {page} 和 {total-pages} 这样的占位符标记,用于动态页码。 有关更多选项,请参阅页眉和页脚文档。
模板变量转换
CraftMyPDF 使用专有模板占位符,必须将其转换为 C# 字符串插值:
CraftMyPDF模式:
//CraftMyPDFtemplate variables
request.AddJsonBody(new
{
template_id = "invoice-template",
data = new
{
customer = "John Doe",
amount = "$1,000",
items = invoiceItems
}
});
//CraftMyPDFtemplate variables
request.AddJsonBody(new
{
template_id = "invoice-template",
data = new
{
customer = "John Doe",
amount = "$1,000",
items = invoiceItems
}
});
'CraftMyPDFtemplate variables
request.AddJsonBody(New With {
.template_id = "invoice-template",
.data = New With {
.customer = "John Doe",
.amount = "$1,000",
.items = invoiceItems
}
})
IronPDF模式:
// C# string interpolation
var html = $@"
<html>
<body>
<h1>Invoice</h1>
<p>Customer: {customerName}</p>
<p>Amount: {amount}</p>
{GenerateItemsTable(invoiceItems)}
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(html);
// C# string interpolation
var html = $@"
<html>
<body>
<h1>Invoice</h1>
<p>Customer: {customerName}</p>
<p>Amount: {amount}</p>
{GenerateItemsTable(invoiceItems)}
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(html);
Dim html As String = $"
<html>
<body>
<h1>Invoice</h1>
<p>Customer: {customerName}</p>
<p>Amount: {amount}</p>
{GenerateItemsTable(invoiceItems)}
</body>
</html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
关键迁移说明
删除所有 HTTP 代码
最重要的变化是消除了网络依赖性。IronPDF在本地运行--无 RestClient、无 API 调用、无响应处理:
//CraftMyPDF- HTTP required
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
var response = await client.ExecuteAsync(request);
//IronPDF- no HTTP
var pdf = renderer.RenderHtmlAsPdf(html);
//CraftMyPDF- HTTP required
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
var response = await client.ExecuteAsync(request);
//IronPDF- no HTTP
var pdf = renderer.RenderHtmlAsPdf(html);
Imports RestSharp
'CraftMyPDF- HTTP required
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
Dim response = Await client.ExecuteAsync(request)
'IronPDF- no HTTP
Dim pdf = renderer.RenderHtmlAsPdf(html)
删除速率限制代码
CraftMyPDF 设置了 API 速率限制,需要重试逻辑。IronPDF没有限制:
//CraftMyPDF- needed to avoid 429 errors
await Task.Delay(100);
if (response.StatusCode == TooManyRequests) { /* retry */ }
//IronPDF- no limits, just generate
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all rate limit code!
//CraftMyPDF- needed to avoid 429 errors
await Task.Delay(100);
if (response.StatusCode == TooManyRequests) { /* retry */ }
//IronPDF- no limits, just generate
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all rate limit code!
删除 Webhook 处理程序
CraftMyPDF 使用异步网络钩子完成 PDF。IronPDF是同步的,PDF 可以立即完成:
//CraftMyPDF- webhook callback required
// POST with webhook_url, wait for callback
//IronPDF- PDF ready immediately
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// No callback needed!
//CraftMyPDF- webhook callback required
// POST with webhook_url, wait for callback
//IronPDF- PDF ready immediately
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// No callback needed!
'CraftMyPDF- webhook callback required
' POST with webhook_url, wait for callback
'IronPDF- PDF ready immediately
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' No callback needed!
默认同步
如果只需要在 HTTP 调用中使用 async/await 模式,则将其删除:
//CraftMyPDF- async required
var response = await client.ExecuteAsync(request);
//IronPDF- sync by default (async available if needed)
var pdf = renderer.RenderHtmlAsPdf(html);
//CraftMyPDF- async required
var response = await client.ExecuteAsync(request);
//IronPDF- sync by default (async available if needed)
var pdf = renderer.RenderHtmlAsPdf(html);
迁移后核对表
完成代码迁移后,请验证以下内容:
- 运行所有 PDF 生成测试
- 比较输出质量(IronPDF 的 Chromium 引擎可实现像素级完美渲染)
- 衡量性能提升(毫秒与秒)
- 验证所有模板是否已正确转换
- 测试无速率限制的批量处理
- 在所有目标环境中进行测试
- 更新 CI/CD 流水线 取消CraftMyPDF订阅
- 从 secrets/config 中移除 API 密钥
未来保护您的 PDF 基础架构
随着 .NET 10 即将推出,C# 14 也将引入新的语言特性,选择本地 PDF 库可以消除云 API 过时风险和版本兼容性问题。IronPDF的永久许可模式意味着您的迁移投资将无限期地获得回报,因为项目将延伸到 2025 年和 2026 年--无需经常性订阅成本或数据离开您的基础架构。
其他资源
从CraftMyPDF迁移到IronPDF可以消除云依赖、网络延迟、每 PDF 成本和模板锁定,同时提供离线运行的像素级完美 Chromium 渲染。从 REST API 调用到本地方法调用的过渡简化了您的代码库,并将敏感文档数据保留在您的基础架构中。

