如何在 C# 中從 Spire.PDF 遷移到 IronPDF
從 Spire.PDF 轉換到IronPDF可將您的 PDF 生成工作流程從將文字渲染為圖像的函式庫轉換為使用現代 Chromium 渲染引擎生成真實、可選、可搜尋文字的函式庫。本指南提供完整的逐步遷移路徑,可解決 Spire.PDF 的關鍵 HTML 渲染限制和字型嵌入問題。
為什麼要從 Spire.PDF 移轉到 IronPDF?
瞭解 Spire.PDF
Spire.PDF 是專為 .NET 開發人員設計的強大商用 PDF 函式庫,可有效率地處理 PDF 文件。 Spire.PDF 因其特殊功能而在程式設計社群中嶄露頭角,尤其是在傳統應用程式中,其整合功能可與 E-iceblue 工具集中的其他元件完美結合。
然而,Spire.PDF 有幾個影響實際使用的基本問題,特別是圍繞 HTML 到 PDF 的轉換和現代網路標準支援。
關鍵技術問題
| 問題 | 影響力 | IronPDF 解決方案 |
|---|---|---|
| 以影像呈現的文字 | PDF 無法搜尋、無法存取、無法複製文字 | 真實文字渲染 |
| Internet Explorer 依賴性 | 過時的渲染、安全風險 | 現代 Chromium 引擎 |
| 字體嵌入失敗 | 文件在其他系統上看起來不對 | 可靠的字型處理 |
| 大量部署足跡 | 記憶體使用率高、啟動速度慢 | 高效部署 |
| 有限的 CSS 支援 | 現代佈局無法正確呈現 | 完全支援 CSS3 |
核心問題:以圖片為基礎的 PDF。
Spire.PDF 的一個顯著缺點是傾向於將 HTML 文件中的文字呈現為影像。 這會導致 PDF 中的文字無法選擇或搜尋,對於需要搜尋功能或文件文字互動的應用程式來說,這可能是一個嚴重的限制。
當您使用 Spire.PDF 的 LoadFromHTML() 方法時,它通常會將文字渲染為點陣圖圖像而不是實際文本,從而導致以下問題:
- 文字不能選擇
- 無法搜尋文字
- 文字不得複製
- 螢幕閱讀器無法閱讀 (違反可存取性)
- 檔案大小較大
- 縮放導致像素化
Spire.PDF 與IronPDF的比較
| 特點 | Spire.PDF | IronPDF |
|---|---|---|
| HTML 至 PDF 渲染 | 以影像呈現的文字 | 真實的文字呈現(可選擇與搜尋) |
| 渲染引擎 | 依賴於某些系統的 Internet Explorer | 基於 Chromium,符合現代網路標準 |
| 字體處理 | 字型嵌入的已知問題 | 可靠、穩健的字型處理 |
| CSS3 支援。 | 限額 | 全文 |
| Flexbox/網格 | 不支援 | 支援 |
| JavaScript。 | 限額 | 完整的 ES6+ |
| PDF 可訪問性 | 差異(以圖像為基礎) | 出色的 |
| API 設計 | 複雜的 | 簡單直觀 |
| 部署足跡 | 大型 | 緩和 |
| 授權 | 免費/商業 | 商業的 |
對於計劃在 2025 年和 2026 年之前採用 .NET 10 和 C# 14 的團隊而言,IronPDF 可解決 Spire.PDF 的 HTML-to-PDF 轉換的關鍵問題,將文字呈現為實際可選擇的文字而非影像,確保 PDF 可搜尋且可存取。
開始之前
先決條件
- .NET環境: .NET Framework 4.6.2+ 或.NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet存取權限:能夠安裝NuGet套件
- IronPDF許可證:請從IronPDF取得您的許可證密鑰。
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
授權組態
// 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: 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
核心 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
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
本範例展示 HTML 呈現的基本差異。 Spire.PDF 使用 LoadFromHTML() 和 PdfHtmlLayoutFormat 對象,該物件通常將文字渲染為點陣圖影像。 結果是使用者無法選擇、複製或搜尋文字的 PDF。
IronPDF 使用 ChromePdfRenderer 和 RenderHtmlAsPdf(),產生完全可選、可搜尋和可存取的真正文字。 無需呼叫 Close() 函數-IronPDF 使用 dispose 模式進行自動清理。有關完整範例,請參閱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
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
Spire.PDF 需要手動載入每個文檔,使用 new PdfDocument() + LoadFromFile(),然後使用 InsertPageRange() 指定要插入的頁面,最後對每個文檔調用 Close() 指定要插入的頁面,最後對每個文檔調用 Close()。
IronPDF 使用更簡單的 PdfDocument.FromFile() 模式和靜態 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
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
Spire.PDF 使用基於畫布的繪圖模型,透過 PdfFont、PdfBrush 和 page.Canvas.DrawString() 將文字定位到特定座標,使用 PointF。
IronPDF 使用 TextStamper 對象,該對象具有 Text、FontSize、VerticalOffset 和 HorizontalOffset 等直觀屬性,然後使用 @@--CODE-19976--@@ 應用它。 這種方法更具宣言性,也更容易維護。
文字即圖片的問題
為什麼這非常重要
當 Spire.PDF 使用影像渲染將 HTML 轉換為 PDF 時,您的文件會失去基本功能:
1. 不支援文字搜尋:使用者無法使用 Ctrl+F 尋找文字。 文件管理系統無法索引內容。
2. 無法選擇/複製文字:嘗試複製引文、參考文獻或資料的使用者無法選擇文字-它顯示的是圖像。
3. 無障礙存取違規:基於影像的 PDF 不符合 WCAG 2.1 標準、第 508 條(美國政府)標準、ADA 要求和螢幕閱讀器相容性要求。
4. 檔案大小較大:相同內容的比較顯示,Spire.PDF(基於圖像)產生的檔案比 IronPDF(基於文字)大 16 倍。
檢測:您的 PDF 是否基於圖像?
開啟 Spire.PDF 產生的文件,並嘗試這些測試:
1.文字選擇:點選並拖曳選擇文字。 如果沒有任何重點 → IMAGE-BASED
- Ctrl+F 搜尋:搜尋頁面上的任何單字。 如果 "未找到匹配內容",請 → IMAGE-BASED 3.複製/貼上:選擇文字並複製到記事本。 如果沒有貼上 → IMAGE-BASED
Internet Explorer 的問題
Spire.PDF 的渲染引擎
在某些環境中,Spire.PDF 依賴 Internet Explorer/Edge Legacy 來呈現 HTML。 IE 已於 2022 年廢棄,現代 CSS 無法運作,JavaScript 支援有限,而且不同系統的呈現方式也不一致。
在 Spire 中失敗的現代 CSS.PDF
<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>
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
現代 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!
基於 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>")
遷移清單
預遷移
- 清點程式碼庫中所有 Spire.PDF 的使用情況
- 測試現有PDF文件的文字選擇性(關鍵問題檢測)
- 文件
LoadFromHTML()呼叫(這些是優先修復的問題) - 從ironpdf.com取得IronPDF許可證金鑰
程式碼更新
- 移除
Spire.PDFNuGet 套件(如果使用免費版本,請移除FreeSpire.PDF) - 安裝
IronPdfNuGet 套件 - 更新命名空間導入(
using Spire.Pdf;→using IronPdf;) - 將
LoadFromHTML()替換為RenderHtmlAsPdf()(關鍵修復) - 將
new PdfDocument()+LoadFromFile()替換為PdfDocument.FromFile() - 將
InsertPageRange()替換為PdfDocument.Merge() - 將
Canvas.DrawString()替換為TextStamper+ApplyStamp() - 將
SaveToFile()替換為SaveAs() - 刪除所有
Close()呼叫(IronPDF 中不需要) - 在應用程式啟動時新增許可證初始化
測試
- 驗證產生的 PDF 檔案中的文字是否可選(關鍵測試)
- 驗證 CSS 渲染改進(Flexbox/Grid 現在可以正常運作)
- 確認檔案大小較小
- 使用螢幕閱讀器測試輔助功能
- 效能比較

