如何用 C# 从 Scryber.Core 迁移到 IronPDF
从Scryber.Core迁移到IronPDF使您的PDF生成工作流从定制的XHTML+CSS布局引擎移动到Chromium渲染器,具有完整的CSS3和JavaScript支持。 本指南提供了逐步迁移路径,涵盖LGPL v3许可考虑,Scryber的XHTML严格模板模型以及两者引擎之间的渲染差异。
为什么要从 Scryber.Core 迁移到 IronPDF.
了解 Scryber.Core.
Scryber.Core(由Richard Hewitson维护,当前版本9.3.1)是一个开源库,其解析XHTML+CSS模板具有自己布局引擎——而非浏览器。 它支持CSS样式、类Handlebars风格的doc.Params,以及SVG,对于希望生成无浏览器依赖的HTML驱动PDF的开发者来说很有吸引力。
尽管Scryber.Core对于基于HTML模板的PDF生成是一个可行的选项,但有一些限制推动团队进行迁移。
迁移的主要原因
- LGPL v3许可关注: 如果您修改Scryber自身,适用源码披露义务; 在闭源应用中静态链接是允许的,但条款仍限制了您如何分发修改。
- XHTML严格输入: 模板必须是有效XML——大多数真实世界的HTML在Scryber解析之前需要清理。
- 非浏览器渲染器: 自定义XHTML/CSS布局引擎——现代CSS(Grid、完整Flexbox、容器查询)和任何JavaScript均不执行。
- 较小社区: 比主流库少的示例。
- 无JavaScript执行: 仅静态渲染——图表、SPA和动态小部件需预渲染。
- 无原生URL到PDF功能: 您必须自己获取HTML(例如使用
HttpClient),然后输入。 - 社区支持: 商业支持选项有限。
Scryber.Core 与IronPDF对比
| 方面 | Scryber.Core | IronPDF |
|---|---|---|
| 许可证 | LGPL v3 | 商业翻译 |
| 渲染引擎 | 自定义XHTML/CSS布局引擎 | Chromium |
| CSS 支持 | 子集(无格栅,部分Flexbox) | 完整的 CSS3 |
| JavaScript | 不执行 | 完整(Chromium V8) |
| 模板绑定 | 类Handlebars风格{{ }} + <template> |
标准(Razor、RazorLight等) |
| 输入严格性 | 需要格式良好的XHTML | 接受真实世界HTML |
| 异步支持 | PDFAsync MVC助手; sync core |
完整异步API |
| 文档 | 阅读文档站点+示例 | 广泛 |
| 社区支持 | 较小 | 较大 |
| 商业支持 | 社区支持 | 提供商业支持 |
IronPDF提供商用支持、文档以及与Scryber.Core相比更大的用户基础。 该库被许可用于商业用途,无LGPL义务。
开始之前
前提条件
- .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet 访问权限:能够安装 NuGet 包
- IronPDF 许可证:请从ironpdf.com获取您的许可证密钥。
NuGet 软件包变更
# Remove Scryber.Core
dotnet remove package Scryber.Core
# Install IronPDF
dotnet add package IronPdf
# Remove Scryber.Core
dotnet remove package Scryber.Core
# Install IronPDF
dotnet add package IronPdf
许可配置
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
完整的 API 参考
命名空间变更
// Before: Scryber.Core
using Scryber.Components; // Document, Page, etc.
using Scryber.Drawing; // Units, colours
using Scryber.PDF; // RenderOptions / OutputCompressionType
using Scryber.Styles; // Style elements (older XML template usage)
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: Scryber.Core
using Scryber.Components; // Document, Page, etc.
using Scryber.Drawing; // Units, colours
using Scryber.PDF; // RenderOptions / OutputCompressionType
using Scryber.Styles; // Style elements (older XML template usage)
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
Imports Scryber.Components ' Document, Page, etc.
Imports Scryber.Drawing ' Units, colours
Imports Scryber.PDF ' RenderOptions / OutputCompressionType
Imports Scryber.Styles ' Style elements (older XML template usage)
' After: IronPDF
Imports IronPdf
Imports IronPdf.Rendering
核心 API 映射
| Scryber.Core | IronPDF |
|---|---|
Document.ParseDocument(reader, "", ParseSourceType.DynamicContent) |
renderer.RenderHtmlAsPdf(html) |
Document.ParseDocument(path) |
renderer.RenderHtmlFileAsPdf(path) |
doc.SaveAsPDF(path) |
pdf.SaveAs(path) |
doc.SaveAsPDF(stream) |
pdf.BinaryData (byte[]) |
doc.Info.Title |
pdf.MetaData.Title |
doc.Info.Author |
pdf.MetaData.Author |
@page模板中的CSS |
renderer.RenderingOptions.PaperSize / 边距 |
doc.RenderOptions |
renderer.RenderingOptions |
Handlebars {{value}} + doc.Params |
Razor/字符串插值 |
代码迁移示例
示例 1:基本 HTML 到 PDF 的转换
之前(Scryber.Core):
// NuGet: Install-Package Scryber.Core
using Scryber.Components;
using System.IO;
class Program
{
static void Main()
{
// Scryber requires well-formed XHTML wrapped in an html root with the xhtml namespace
string html = @"<html xmlns='http://www.w3.org/1999/xhtml'>
<body><h1>Hello World</h1><p>This is a PDF document.</p></body>
</html>";
using (var reader = new StringReader(html))
using (var doc = Document.ParseDocument(reader, string.Empty, ParseSourceType.DynamicContent))
using (var stream = new FileStream("output.pdf", FileMode.Create))
{
doc.SaveAsPDF(stream);
}
}
}
// NuGet: Install-Package Scryber.Core
using Scryber.Components;
using System.IO;
class Program
{
static void Main()
{
// Scryber requires well-formed XHTML wrapped in an html root with the xhtml namespace
string html = @"<html xmlns='http://www.w3.org/1999/xhtml'>
<body><h1>Hello World</h1><p>This is a PDF document.</p></body>
</html>";
using (var reader = new StringReader(html))
using (var doc = Document.ParseDocument(reader, string.Empty, ParseSourceType.DynamicContent))
using (var stream = new FileStream("output.pdf", FileMode.Create))
{
doc.SaveAsPDF(stream);
}
}
}
Imports Scryber.Components
Imports System.IO
Class Program
Shared Sub Main()
' Scryber requires well-formed XHTML wrapped in an html root with the xhtml namespace
Dim html As String = "<html xmlns='http://www.w3.org/1999/xhtml'>" &
"<body><h1>Hello World</h1><p>This is a PDF document.</p></body>" &
"</html>"
Using reader As New StringReader(html),
doc As Document = Document.ParseDocument(reader, String.Empty, ParseSourceType.DynamicContent),
stream As New FileStream("output.pdf", FileMode.Create)
doc.SaveAsPDF(stream)
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
string html = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer = New ChromePdfRenderer()
Dim html As String = "<html><body><h1>Hello World</h1><p>This is a PDF document.</p></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class
Scryber.Core将XHTML字符串包装在FileStream。 需要XHTML命名空间声明—Scryber将拒绝不符合XML格式的HTML。
IronPDF使用SaveAs()保存。 真实世界HTML5可以按原样接受。 更多示例请参阅HTML到PDF文档。
示例 2:URL 到 PDF 的转换
之前(Scryber.Core):
// NuGet: Install-Package Scryber.Core
// Scryber has no native URL-to-PDF method — fetch the HTML yourself, then parse.
using Scryber.Components;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var client = new HttpClient();
string html = await client.GetStringAsync("https://www.example.com");
// Most live HTML is not valid XHTML; expect to clean it
// (e.g., HtmlAgilityPack) before Scryber will parse it.
using (var reader = new StringReader(html))
using (var doc = Document.ParseDocument(reader, string.Empty, ParseSourceType.DynamicContent))
using (var stream = new FileStream("webpage.pdf", FileMode.Create))
{
doc.SaveAsPDF(stream);
}
}
}
// NuGet: Install-Package Scryber.Core
// Scryber has no native URL-to-PDF method — fetch the HTML yourself, then parse.
using Scryber.Components;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var client = new HttpClient();
string html = await client.GetStringAsync("https://www.example.com");
// Most live HTML is not valid XHTML; expect to clean it
// (e.g., HtmlAgilityPack) before Scryber will parse it.
using (var reader = new StringReader(html))
using (var doc = Document.ParseDocument(reader, string.Empty, ParseSourceType.DynamicContent))
using (var stream = new FileStream("webpage.pdf", FileMode.Create))
{
doc.SaveAsPDF(stream);
}
}
}
Imports Scryber.Components
Imports System.IO
Imports System.Net.Http
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using client As New HttpClient()
Dim html As String = Await client.GetStringAsync("https://www.example.com")
' Most live HTML is not valid XHTML; expect to clean it
' (e.g., HtmlAgilityPack) before Scryber will parse it.
Using reader As New StringReader(html)
Using doc As Document = Document.ParseDocument(reader, String.Empty, ParseSourceType.DynamicContent)
Using stream As New FileStream("webpage.pdf", FileMode.Create)
doc.SaveAsPDF(stream)
End Using
End Using
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
Scryber.Core没有原生URL-to-PDF入口。 您可以使用Document.ParseDocument()中。 由于Scryber要求格式良好的XHTML,大多数动态页面在解析之前需要进行清理(例如通过HtmlAgilityPack)。 JavaScript不执行,所以任何动态渲染的内容都会丢失。
IronPDF的RenderUrlAsPdf()在一次调用中通过其Chromium引擎处理获取、JavaScript执行和CSS渲染。更多信息请参阅我们的教程。
示例 3:自定义页面设置和页边距
之前(Scryber.Core):
// NuGet: Install-Package Scryber.Core
// Page size and margins are normally declared in the XHTML/CSS template;
// the runtime RenderOptions object exposes output-side settings such as compression.
using Scryber.Components;
using Scryber.PDF;
using System.IO;
class Program
{
static void Main()
{
// Page size and margins go in CSS @page; this is the Scryber idiom.
string html = @"<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<style>
@page { size: A4 portrait; margin: 40pt; }
</style>
</head>
<body><h1>Custom PDF</h1><p>With custom margins and settings.</p></body>
</html>";
using (var reader = new StringReader(html))
using (var doc = Document.ParseDocument(reader, string.Empty, ParseSourceType.DynamicContent))
using (var stream = new FileStream("custom.pdf", FileMode.Create))
{
// Output-side options (compression / conformance) are on RenderOptions.
doc.RenderOptions.Compression = OutputCompressionType.FlateDecode;
doc.SaveAsPDF(stream);
}
}
}
// NuGet: Install-Package Scryber.Core
// Page size and margins are normally declared in the XHTML/CSS template;
// the runtime RenderOptions object exposes output-side settings such as compression.
using Scryber.Components;
using Scryber.PDF;
using System.IO;
class Program
{
static void Main()
{
// Page size and margins go in CSS @page; this is the Scryber idiom.
string html = @"<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<style>
@page { size: A4 portrait; margin: 40pt; }
</style>
</head>
<body><h1>Custom PDF</h1><p>With custom margins and settings.</p></body>
</html>";
using (var reader = new StringReader(html))
using (var doc = Document.ParseDocument(reader, string.Empty, ParseSourceType.DynamicContent))
using (var stream = new FileStream("custom.pdf", FileMode.Create))
{
// Output-side options (compression / conformance) are on RenderOptions.
doc.RenderOptions.Compression = OutputCompressionType.FlateDecode;
doc.SaveAsPDF(stream);
}
}
}
Imports Scryber.Components
Imports Scryber.PDF
Imports System.IO
Module Program
Sub Main()
' Page size and margins go in CSS @page; this is the Scryber idiom.
Dim html As String = "<html xmlns='http://www.w3.org/1999/xhtml'>" &
"<head>" &
"<style>" &
"@page { size: A4 portrait; margin: 40pt; }" &
"</style>" &
"</head>" &
"<body><h1>Custom PDF</h1><p>With custom margins and settings.</p></body>" &
"</html>"
Using reader As New StringReader(html),
doc As Document = Document.ParseDocument(reader, String.Empty, ParseSourceType.DynamicContent),
stream As New FileStream("custom.pdf", FileMode.Create)
' Output-side options (compression / conformance) are on RenderOptions.
doc.RenderOptions.Compression = OutputCompressionType.FlateDecode
doc.SaveAsPDF(stream)
End Using
End Sub
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 40;
renderer.RenderingOptions.MarginBottom = 40;
string html = "<html><body><h1>Custom PDF</h1><p>With custom margins and settings.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 40;
renderer.RenderingOptions.MarginBottom = 40;
string html = "<html><body><h1>Custom PDF</h1><p>With custom margins and settings.</p></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 40
renderer.RenderingOptions.MarginBottom = 40
Dim html As String = "<html><body><h1>Custom PDF</h1><p>With custom margins and settings.</p></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("custom.pdf")
End Sub
End Class
在Scryber.Core中,页面大小和边距在模板中通过@page CSS声明,而OutputCompressionType.FlateDecode)。
IronPDF将页面几何体移动到渲染器上的MarginBottom以毫米为单位。 页面几何体存在于API表面而非模板内部。
模板迁移模式
迁移Scryber绑定到标准模板
Scryber.Core使用XHTML结合类Handlebars风格的<template data-bind='...'>构造。 要迁移,请在标准.NET模板中重新表达这些:
Scryber绑定(XHTML + Handlebars):
<p>{{model.Name}}</p>
<p>Total: {{model.Total}}</p>
<template data-bind='{{model.Items}}'>
<p>{{.Name}}: {{.Price}}</p>
</template>
<p>{{model.Name}}</p>
<p>Total: {{model.Total}}</p>
<template data-bind='{{model.Items}}'>
<p>{{.Name}}: {{.Price}}</p>
</template>
使用 C# 字符串插值的 IronPDF:
var items = model.Items.Select(i => $"<li>{i.Name}: {i.Price:C}</li>");
var html = $@"
<p>{model.Name}</p>
<p>Total: {model.Total:C}</p>
<ul>
{string.Join("", items)}
</ul>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
var items = model.Items.Select(i => $"<li>{i.Name}: {i.Price:C}</li>");
var html = $@"
<p>{model.Name}</p>
<p>Total: {model.Total:C}</p>
<ul>
{string.Join("", items)}
</ul>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
Dim items = model.Items.Select(Function(i) $"<li>{i.Name}: {i.Price:C}</li>")
Dim html = $"
<p>{model.Name}</p>
<p>Total: {model.Total:C}</p>
<ul>
{String.Join("", items)}
</ul>"
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
由于IronPDF接受纯HTML,您可以使用任何.NET模板引擎(Razor、RazorLight、Handlebars.Net),而不是Scryber的{{ }} + <template>构造。
页眉和页脚迁移
Scryber.Core(XHTML + @page边距盒):
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<style>
@page {
@top-center { content: 'Company Report'; }
@bottom-center { content: 'Page ' counter(page) ' of ' counter(pages); }
}
</style>
</head>
<body>
<h1>Content Here</h1>
</body>
</html>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<style>
@page {
@top-center { content: 'Company Report'; }
@bottom-center { content: 'Page ' counter(page) ' of ' counter(pages); }
}
</style>
</head>
<body>
<h1>Content Here</h1>
</body>
</html>
IronPDF(HTML 页眉/页脚):
using IronPdf;
var renderer = new ChromePdfRenderer();
// HTML header with full CSS support
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='width: 100%; text-align: center; font-size: 12pt; border-bottom: 1px solid #ccc;'>
Company Report
</div>",
MaxHeight = 30
};
// HTML footer with page numbers
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='width: 100%; text-align: center; font-size: 10pt;'>
Page {page} of {total-pages}
</div>",
MaxHeight = 25
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Content Here</h1>");
pdf.SaveAs("report.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
// HTML header with full CSS support
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='width: 100%; text-align: center; font-size: 12pt; border-bottom: 1px solid #ccc;'>
Company Report
</div>",
MaxHeight = 30
};
// HTML footer with page numbers
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = @"
<div style='width: 100%; text-align: center; font-size: 10pt;'>
Page {page} of {total-pages}
</div>",
MaxHeight = 25
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Content Here</h1>");
pdf.SaveAs("report.pdf");
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
' HTML header with full CSS support
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter With {
.HtmlFragment = "
<div style='width: 100%; text-align: center; font-size: 12pt; border-bottom: 1px solid #ccc;'>
Company Report
</div>",
.MaxHeight = 30
}
' HTML footer with page numbers
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.HtmlFragment = "
<div style='width: 100%; text-align: center; font-size: 10pt;'>
Page {page} of {total-pages}
</div>",
.MaxHeight = 25
}
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Content Here</h1>")
pdf.SaveAs("report.pdf")
Scryber.Core通过CSS中的counter(pages)用于页码。 IronPDF使用带完整HTML/CSS的{total-pages}。
迁移后的新功能
迁移到IronPDF后,您将获得 Scryber.Core 无法提供的功能:
PDF 合并
var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var pdf3 = PdfDocument.FromFile("chapter3.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete_book.pdf");
var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var pdf3 = PdfDocument.FromFile("chapter3.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete_book.pdf");
Dim pdf1 = PdfDocument.FromFile("chapter1.pdf")
Dim pdf2 = PdfDocument.FromFile("chapter2.pdf")
Dim pdf3 = PdfDocument.FromFile("chapter3.pdf")
Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("complete_book.pdf")
安全性和元数据
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");
// Metadata
pdf.MetaData.Title = "My Document";
pdf.MetaData.Author = "John Doe";
pdf.MetaData.Subject = "Annual Report";
pdf.MetaData.Keywords = "report, annual, confidential";
// Security
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user456";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SaveAs("protected.pdf");
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");
// Metadata
pdf.MetaData.Title = "My Document";
pdf.MetaData.Author = "John Doe";
pdf.MetaData.Subject = "Annual Report";
pdf.MetaData.Keywords = "report, annual, confidential";
// Security
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user456";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
pdf.SaveAs("protected.pdf");
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>")
' Metadata
pdf.MetaData.Title = "My Document"
pdf.MetaData.Author = "John Doe"
pdf.MetaData.Subject = "Annual Report"
pdf.MetaData.Keywords = "report, annual, confidential"
' Security
pdf.SecuritySettings.OwnerPassword = "owner123"
pdf.SecuritySettings.UserPassword = "user456"
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights
pdf.SaveAs("protected.pdf")
功能对比摘要
| 特征 | Scryber.Core | IronPDF |
|---|---|---|
| HTML 至 PDF | XHTML+CSS通过自定义布局引擎 | 完整的 Chromium |
| URL 至 PDF | 仅手动获取 | 原生RenderUrlAsPdf |
| CSS 网格 | 不支持 | 全面支持 |
| Flexbox | 部分翻译 | 全面支持 |
| JavaScript | 不执行 | 完整(V8) |
| 数据绑定 | {{ }} Handlebars + doc.Params |
Razor / RazorLight / 插值 |
| 页眉/页脚 | @page 边距盒 / 模板部分 |
HtmlHeaderFooter 使用{page} {total-pages} |
| 合并 PDF | 不支持 | 内置PdfDocument.Merge |
| 拆分 PDF | 不支持 | 是 |
| 水印 | 通过模板中的叠加HTML | 原生ApplyStamp / ApplyWatermark |
| 数字签名 | 不支持 | 是 |
| PDF/A | 不支持 | 是(PDF/A-1b, PDF/A-3) |
| 密码保护 | 不支持 | 完整(用户/所有者 + 权限) |
| 异步支持 | PDFAsync MVC助手; sync core |
完整异步界面 |
| 跨平台 | 是(.NET Std 2.0/2.1, .NET 8/9/10) | 是 |
迁移清单
迁移前
- 审核所有Scryber模板的XHTML/绑定模式
- 使用的文档数据绑定模式(
{{model.Property}}) - 识别需要进行 CSS 转换的自定义样式
- 从ironpdf.com获取IronPDF许可证密钥
代码更新
- 移除
Scryber.CoreNuGet包 - 安装
IronPdfNuGet包 - 更新命名空间导入(
using Scryber.Components;/Scryber.Drawing;/Scryber.PDF;→using IronPdf;) - 用
Document.ParseDocument(reader, "", ParseSourceType.DynamicContent) - 用
doc.SaveAsPDF(stream) - 将XHTML模板转换为纯HTML5(无命名空间要求)
- 用标准模板(Razor / 字符串插值)替换
{{ }}Handlebars绑定 - 将
@pageCSS 移动到renderer.RenderingOptions(PaperSize、MarginTop等) - 将
{total-pages}占位符 - 在应用程序启动时添加许可证初始化
测试
- 测试所有文档模板
- 验证样式是否匹配(充分利用 CSS 支持)
- 使用新模板测试数据绑定
- 验证分页符
- 测试带有页码占位符的页眉/页脚
- 性能比较

