跳至页脚内容
视频

如何在 NET MAUI 中将 XAML 转换为 PDF | IronPDF

从 Spire.PDF 迁移到IronPDF将您的 PDF 生成工作从经常产生基于图像文本的遗留 HTML 路径迁移到一个产生真实、可选择、可搜索文本的 Chromium 管道。 本指南提供了完整的、逐步的迁移路径,涵盖了 Spire.PDF 的 HTML 渲染权衡和报告的字体嵌入问题。

为什么要从 Spire.PDF 迁移到 IronPDF.

了解 Spire.PDF.

Spire.PDF 是一个功能强大的商用 PDF 库,专为 .NET 开发人员高效处理 PDF 文档而设计。 Spire.PDF 因其特殊功能(尤其是在传统应用程序中)而在编程界声名鹊起,其集成功能可与 E-iceblue 工具集中的其他组件无缝对接。

然而,Spire.PDF 存在几个影响实际使用的基本问题,特别是 HTML 到 PDF 的转换和对现代网络标准的支持。

关键技术问题

问题 影响 IronPDF 解决方案
文本经常在遗留 HTML 路径上渲染为图像 PDF 无法搜索、无法访问、无法复制文本 真实文本渲染
IE/Edge 遗留或 QtWebKit 对遗留路径的依赖 过时的渲染,现代 CSS 问题 捆绑的现代 Chromium
报告的字体嵌入问题 文件在其他系统上看起来不对 可靠的字体处理
大量部署足迹 较高的内存使用 捆绑的 Chromium 运行时
遗留路径上的 CSS 限制 现代布局无法正确呈现 完全支持 CSS3

核心问题:基于图像的 PDF 文件

Spire.PDF 的遗留 HTML 路径一个被报告的缺点是其倾向于将 HTML 文档内的文本渲染为图像。 这会产生 PDF,其中的文本不可选择也不可搜索——对于需要搜索或文本交互的应用程序来说是一个限制。

当您在传统引擎上使用Spire.PDF的LoadFromHTML()方法时,它通常将文字呈现为位图图像而不是实际文本,造成以下问题:

  • 文本不能选择
  • 不能搜索文本
  • 文本不得复制
  • 屏幕阅读器无法阅读(违反可访问性原则)
  • 文件较大
  • 缩放导致像素化

Spire.PDF 与IronPDF对比

特征 Spire.PDF IronPDF
HTML 到 PDF 渲染 默认采用遗留 IE/QtWebKit; 选择加入ChromeHtmlConverter(需要系统Chrome)自v10.7.21以来 捆绑 Chromium(现代,无需额外安装)
文本输出(HTML 路径) 经常在遗留路径上渲染为图像 真实文本(可选择和可搜索)
字体处理 遗留路径上的问题报告 可靠的字体处理
CSS3 支持 遗留路径上的限制 满的
Flexbox/网格 遗留路径不支持 支持
JavaScript语言 遗留路径上的限制 完整的 ES6+
PDF 辅助功能 遗留路径上的表现不佳(基于图像的输出) 标记文本输出
API 设计 许多重载,手动页面设置 单一流畅渲染器
许可 免费/商业 商业翻译

在现代 .NET 上,IronPDF 通过渲染文本为实际的可选择文本而非图像来解决 Spire.PDF 的 HTML 到 PDF 的权衡,因此生成的 PDF 是可搜索和可访问的。


开始之前

前提条件

  1. .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet 访问权限:能够安装 NuGet 包
  3. IronPDF 许可证:请从ironpdf.com获取您的许可证密钥。

NuGet 软件包变更

# Remove Spire.PDF
dotnet remove package Spire.PDF
dotnet remove package FreeSpire.PDF  # If using free version

# Install IronPDF
dotnet add package IronPdf
# Remove Spire.PDF
dotnet remove package Spire.PDF
dotnet remove package FreeSpire.PDF  # If using free version

# Install IronPDF
dotnet add package IronPdf
SHELL

许可配置

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

完整的 API 参考

命名空间变更

// Before: Spire.PDF
using Spire.Pdf;
using Spire.Pdf.Graphics;
using Spire.Pdf.HtmlConverter;

// After: IronPDF
using IronPdf;
using IronPdf.Editing;
// Before: Spire.PDF
using Spire.Pdf;
using Spire.Pdf.Graphics;
using Spire.Pdf.HtmlConverter;

// After: IronPDF
using IronPdf;
using IronPdf.Editing;
Imports IronPdf
Imports IronPdf.Editing
$vbLabelText   $csharpLabel

核心 API 映射

Spire.PDF IronPDF
new PdfDocument() new ChromePdfRenderer()
pdf.LoadFromHTML() renderer.RenderHtmlAsPdf()
pdf.LoadFromFile() PdfDocument.FromFile()
pdf.SaveToFile() pdf.SaveAs()
pdf.Close() 不需要
pdf.Pages.Add() renderer.RenderHtmlAsPdf()
pdf.InsertPageRange() PdfDocument.Merge()
page.Canvas.DrawString() TextStamper + ApplyStamp()
PdfFont HTML 中的 CSS 样式
PdfBrush HTML 中的 CSS 样式

代码迁移示例

示例 1:HTML 到 PDF 的转换

之前 (Spire.PDF):

// NuGet: Install-Package Spire.PDF
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System;

class Program
{
    static void Main()
    {
        PdfDocument pdf = new PdfDocument();
        PdfHtmlLayoutFormat htmlLayoutFormat = new PdfHtmlLayoutFormat();

        string htmlString = "<html><body><h1>Hello World</h1><p>This is a PDF from HTML.</p></body></html>";

        pdf.LoadFromHTML(htmlString, false, true, true);
        pdf.SaveToFile("output.pdf");
        pdf.Close();
    }
}
// NuGet: Install-Package Spire.PDF
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System;

class Program
{
    static void Main()
    {
        PdfDocument pdf = new PdfDocument();
        PdfHtmlLayoutFormat htmlLayoutFormat = new PdfHtmlLayoutFormat();

        string htmlString = "<html><body><h1>Hello World</h1><p>This is a PDF from HTML.</p></body></html>";

        pdf.LoadFromHTML(htmlString, false, true, true);
        pdf.SaveToFile("output.pdf");
        pdf.Close();
    }
}
Imports Spire.Pdf
Imports Spire.Pdf.Graphics
Imports System

Class Program
    Shared Sub Main()
        Dim pdf As New PdfDocument()
        Dim htmlLayoutFormat As New PdfHtmlLayoutFormat()

        Dim htmlString As String = "<html><body><h1>Hello World</h1><p>This is a PDF from HTML.</p></body></html>"

        pdf.LoadFromHTML(htmlString, False, True, True)
        pdf.SaveToFile("output.pdf")
        pdf.Close()
    End Sub
End Class
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();

        string htmlString = "<html><body><h1>Hello World</h1><p>This is a PDF from HTML.</p></body></html>";

        var pdf = renderer.RenderHtmlAsPdf(htmlString);
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();

        string htmlString = "<html><body><h1>Hello World</h1><p>This is a PDF from HTML.</p></body></html>";

        var pdf = renderer.RenderHtmlAsPdf(htmlString);
        pdf.SaveAs("output.pdf");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()

        Dim htmlString As String = "<html><body><h1>Hello World</h1><p>This is a PDF from HTML.</p></body></html>"

        Dim pdf = renderer.RenderHtmlAsPdf(htmlString)
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

本例展示了 HTML 渲染的根本区别。 Spire.PDF使用PdfHtmlLayoutFormat对象,通常将文字呈现为位图图像。 结果是用户无法选择、复制或搜索文本的 PDF 文件。

IronPDF使用RenderHtmlAsPdf(),生成真实的文本,完全可选择、可搜索、可访问。 不需要Close()调用——IronPDF使用释放模式进行自动清理。有关全面示例,请参阅HTML转PDF文档

示例 2:合并多个 PDF 文件

之前 (Spire.PDF):

// NuGet: Install-Package Spire.PDF
using Spire.Pdf;
using System;

class Program
{
    static void Main()
    {
        PdfDocument pdf1 = new PdfDocument();
        pdf1.LoadFromFile("document1.pdf");

        PdfDocument pdf2 = new PdfDocument();
        pdf2.LoadFromFile("document2.pdf");

        pdf1.InsertPageRange(pdf2, 0, pdf2.Pages.Count - 1);

        pdf1.SaveToFile("merged.pdf");
        pdf1.Close();
        pdf2.Close();
    }
}
// NuGet: Install-Package Spire.PDF
using Spire.Pdf;
using System;

class Program
{
    static void Main()
    {
        PdfDocument pdf1 = new PdfDocument();
        pdf1.LoadFromFile("document1.pdf");

        PdfDocument pdf2 = new PdfDocument();
        pdf2.LoadFromFile("document2.pdf");

        pdf1.InsertPageRange(pdf2, 0, pdf2.Pages.Count - 1);

        pdf1.SaveToFile("merged.pdf");
        pdf1.Close();
        pdf2.Close();
    }
}
Imports Spire.Pdf
Imports System

Class Program
    Shared Sub Main()
        Dim pdf1 As New PdfDocument()
        pdf1.LoadFromFile("document1.pdf")

        Dim pdf2 As New PdfDocument()
        pdf2.LoadFromFile("document2.pdf")

        pdf1.InsertPageRange(pdf2, 0, pdf2.Pages.Count - 1)

        pdf1.SaveToFile("merged.pdf")
        pdf1.Close()
        pdf2.Close()
    End Sub
End Class
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var pdf1 = PdfDocument.FromFile("document1.pdf");
        var pdf2 = PdfDocument.FromFile("document2.pdf");

        var merged = PdfDocument.Merge(pdf1, pdf2);

        merged.SaveAs("merged.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var pdf1 = PdfDocument.FromFile("document1.pdf");
        var pdf2 = PdfDocument.FromFile("document2.pdf");

        var merged = PdfDocument.Merge(pdf1, pdf2);

        merged.SaveAs("merged.pdf");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim pdf1 = PdfDocument.FromFile("document1.pdf")
        Dim pdf2 = PdfDocument.FromFile("document2.pdf")

        Dim merged = PdfDocument.Merge(pdf1, pdf2)

        merged.SaveAs("merged.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

Spire.PDF需要手动加载每个文档,通过new PdfDocument() + Close()

IronPDF使用更简单的PdfDocument.Merge()方法,接受多个文档。 不需要Close()调用。 在我们的教程中了解更多信息。

示例 3:向 PDF 添加文本

之前 (Spire.PDF):

// NuGet: Install-Package Spire.PDF
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;
using System;

class Program
{
    static void Main()
    {
        PdfDocument pdf = new PdfDocument();
        PdfPageBase page = pdf.Pages.Add();

        PdfFont font = new PdfFont(PdfFontFamily.Helvetica, 20);
        PdfBrush brush = new PdfSolidBrush(Color.Black);

        page.Canvas.DrawString("Hello from Spire.PDF!", font, brush, new PointF(50, 50));

        pdf.SaveToFile("output.pdf");
        pdf.Close();
    }
}
// NuGet: Install-Package Spire.PDF
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;
using System;

class Program
{
    static void Main()
    {
        PdfDocument pdf = new PdfDocument();
        PdfPageBase page = pdf.Pages.Add();

        PdfFont font = new PdfFont(PdfFontFamily.Helvetica, 20);
        PdfBrush brush = new PdfSolidBrush(Color.Black);

        page.Canvas.DrawString("Hello from Spire.PDF!", font, brush, new PointF(50, 50));

        pdf.SaveToFile("output.pdf");
        pdf.Close();
    }
}
Imports Spire.Pdf
Imports Spire.Pdf.Graphics
Imports System.Drawing
Imports System

Class Program
    Shared Sub Main()
        Dim pdf As New PdfDocument()
        Dim page As PdfPageBase = pdf.Pages.Add()

        Dim font As New PdfFont(PdfFontFamily.Helvetica, 20)
        Dim brush As PdfBrush = New PdfSolidBrush(Color.Black)

        page.Canvas.DrawString("Hello from Spire.PDF!", font, brush, New PointF(50, 50))

        pdf.SaveToFile("output.pdf")
        pdf.Close()
    End Sub
End Class
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Editing;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<html><body></body></html>");

        var textStamper = new TextStamper()
        {
            Text = "Hello from IronPDF!",
            FontSize = 20,
            VerticalOffset = 50,
            HorizontalOffset = 50
        };

        pdf.ApplyStamp(textStamper);
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Editing;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<html><body></body></html>");

        var textStamper = new TextStamper()
        {
            Text = "Hello from IronPDF!",
            FontSize = 20,
            VerticalOffset = 50,
            HorizontalOffset = 50
        };

        pdf.ApplyStamp(textStamper);
        pdf.SaveAs("output.pdf");
    }
}
Imports IronPdf
Imports IronPdf.Editing
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<html><body></body></html>")

        Dim textStamper = New TextStamper() With {
            .Text = "Hello from IronPDF!",
            .FontSize = 20,
            .VerticalOffset = 50,
            .HorizontalOffset = 50
        }

        pdf.ApplyStamp(textStamper)
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

Spire.PDF使用基于画布的绘图模型,通过PointF将文本定位于特定坐标。

IronPDF使用ApplyStamp()应用。 这种方法更具声明性,更易于维护。


文本即图像问题

为什么这一点至关重要

当 Spire.PDF 使用基于图像的渲染技术将 HTML 转换为 PDF 时,您的文档将失去基本功能:

1. 不支持文本搜索:用户无法使用 Ctrl+F 查找文本。 文档管理系统无法对内容进行索引。

2. 无法选择/复制文本:尝试复制引文、参考文献或数据的用户无法选择文本——它显示的是图像。

3. 无障碍访问违规:基于图像的 PDF 不符合 WCAG 2.1 标准、第 508 条(美国政府)标准、ADA 要求和屏幕阅读器兼容性要求。

4. 大文件大小:遗留 HTML 路径的基于图像的输出产生的文件尺寸可能比相同内容的IronPDF的基于文本的输出大一个数量级。

检测:您的 PDF 是否基于图像?

打开 Spire.PDF 生成的文档并尝试这些测试:

1.文本选择:点击并拖动选择文本。 如果没有什么亮点 → 基于图像

  1. Ctrl+F 搜索:搜索页面上的任何单词。 如果 "未找到匹配内容",请选择 "基于图像"。 3.复制/粘贴:选择文本并复制到记事本。 如果没有粘贴 → 基于图像

遗留 HTML 引擎问题

Spire.PDF 的渲染引擎

Spire.PDF的LoadFromHTML(...)历史上提供了两种路径:通过Windows Internet Explorer / Edge传统WebBrowser控件的非插件路径,以及通过单独下载的QT/WebKit插件路径。 Spire.PDF 10.7.21(2024年中)添加了第三种选项ChromeHtmlConverter,它调用本地安装的Google Chrome —— 但这是选择加入,原始的LoadFromHTML API仍然默认为传统引擎。 IE/Edge 遗留由微软在2022年弃用,现代 CSS 在遗留路径上不可靠,JavaScript 支持是部分的,渲染可能在不同系统之间有所不同。

在 Spire.PDF 中失效的现代 CSS.


<div style="display: flex; justify-content: space-between; gap: 20px;">
    <div style="flex: 1;">Column 1</div>
    <div style="flex: 1;">Column 2</div>
</div>

<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
</div>

<style>
:root { --primary-color: #007bff; }
h1 { color: var(--primary-color); }
</style>

<div style="display: flex; justify-content: space-between; gap: 20px;">
    <div style="flex: 1;">Column 1</div>
    <div style="flex: 1;">Column 2</div>
</div>

<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
</div>

<style>
:root { --primary-color: #007bff; }
h1 { color: var(--primary-color); }
</style>
HTML

IronPDF 使用现代 Chromium 渲染技术,因此所有这些 CSS 功能都能正常工作。


迁移后的新功能

迁移到IronPDF后,您将获得 Spire.PDF 无法提供的功能:

可选择、可搜索文本

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Important Contract</h1>");
pdf.SaveAs("contract.pdf");

// Result:
// ✅ Text is fully selectable
// ✅ Text is searchable with Ctrl+F
// ✅ Text can be copied to clipboard
// ✅ Screen readers work perfectly
// ✅ File size is compact
// ✅ Zooming is crystal clear
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Important Contract</h1>");
pdf.SaveAs("contract.pdf");

// Result:
// ✅ Text is fully selectable
// ✅ Text is searchable with Ctrl+F
// ✅ Text can be copied to clipboard
// ✅ Screen readers work perfectly
// ✅ File size is compact
// ✅ Zooming is crystal clear
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Important Contract</h1>")
pdf.SaveAs("contract.pdf")

' Result:
' ✅ Text is fully selectable
' ✅ Text is searchable with Ctrl+F
' ✅ Text can be copied to clipboard
' ✅ Screen readers work perfectly
' ✅ File size is compact
' ✅ Zooming is crystal clear
$vbLabelText   $csharpLabel

现代 CSS 支持

var renderer = new ChromePdfRenderer();

var html = @"
<style>
    :root { --primary: #007bff; }
    .container { display: flex; gap: 20px; }
    .grid { display: grid; grid-template-columns: repeat(3, 1fr); }
</style>
<div class='container'>
    <div style='flex: 1; color: var(--primary)'>Column 1</div>
    <div style='flex: 1'>Column 2</div>
</div>
<div class='grid'>
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
</div>";

var pdf = renderer.RenderHtmlAsPdf(html);
// All modern CSS features render correctly!
var renderer = new ChromePdfRenderer();

var html = @"
<style>
    :root { --primary: #007bff; }
    .container { display: flex; gap: 20px; }
    .grid { display: grid; grid-template-columns: repeat(3, 1fr); }
</style>
<div class='container'>
    <div style='flex: 1; color: var(--primary)'>Column 1</div>
    <div style='flex: 1'>Column 2</div>
</div>
<div class='grid'>
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
</div>";

var pdf = renderer.RenderHtmlAsPdf(html);
// All modern CSS features render correctly!
Dim renderer = New ChromePdfRenderer()

Dim html = "
<style>
    :root { --primary: #007bff; }
    .container { display: flex; gap: 20px; }
    .grid { display: grid; grid-template-columns: repeat(3, 1fr); }
</style>
<div class='container'>
    <div style='flex: 1; color: var(--primary)'>Column 1</div>
    <div style='flex: 1'>Column 2</div>
</div>
<div class='grid'>
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
</div>"

Dim pdf = renderer.RenderHtmlAsPdf(html)
' All modern CSS features render correctly!
$vbLabelText   $csharpLabel

基于 HTML 的水印

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.ApplyWatermark(@"
    <div style='
        font-size: 48px;
        color: rgba(255, 0, 0, 0.5);
        transform: rotate(-45deg);
    '>DRAFT</div>");
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.ApplyWatermark(@"
    <div style='
        font-size: 48px;
        color: rgba(255, 0, 0, 0.5);
        transform: rotate(-45deg);
    '>DRAFT</div>");
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.ApplyWatermark("
    <div style='
        font-size: 48px;
        color: rgba(255, 0, 0, 0.5);
        transform: rotate(-45deg);
    '>DRAFT</div>")
$vbLabelText   $csharpLabel

迁移清单

迁移前

  • 清点代码库中所有 Spire.PDF 的使用情况
  • 测试现有PDF文件的文本选择性(关键问题检测)
  • 文档LoadFromHTML()调用(这些是优先修复的)
  • ironpdf.com获取IronPDF许可证密钥

代码更新

  • 移除Spire.PDF NuGet包(如果使用免费版本则也移除FreeSpire.PDF
  • 安装IronPdf NuGet包
  • 更新命名空间导入(using Spire.Pdf;using IronPdf;
  • LoadFromHTML()(关键修复)
  • new PdfDocument() + LoadFromFile()
  • InsertPageRange()
  • TextStamper + Canvas.DrawString()
  • SaveToFile()
  • 移除所有Close()调用(在IronPDF中不需要)
  • 在应用程序启动时添加许可证初始化

测试

  • 验证生成的 PDF 文件中的文本是否可选(关键测试)
  • 验证 CSS 渲染改进(Flexbox/Grid 现在可以正常工作)
  • 确认文件大小较小
  • 使用屏幕阅读器测试辅助功能
  • 性能比较

请注意Spire 是其相应所有者的注册商标。 本网站与 e-iceblue 无关、未获得其认可或赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我