
如何在Mac上編輯PDF
在開發需要PDF生成和操作功能的現代.NET應用程式時,選擇合適的程式庫可以顯著影響專案的成功。 在.NET生態系統中有兩個顯著的選擇:IronPDF和PDFSharpCore,每個選擇都提供了獨特的PDF處理方法。 這個全面的比較將幫助您根據您的具體需求、預算和技術需求做出明智的決定。
快速比較概覽
在深入了解技術細節之前,這裡有一張全面的比較表,總結了IronPDF和PDFSharpCore之間的關鍵差異:
| 類別 | 功能/方面 | IronPDF | PDFSharpCore | 關鍵優勢 |
|---|---|---|---|---|
| 核心架構 | 設計理念 | 基於Chrome的渲染,直觀的API | 輕量化,手動PDF構建 | IronPDF:更快的開發 |
| API複雜性 | 簡單的方法如RenderHtmlAsPdf() | 使用XGraphics手動繪圖 | IronPDF:簡單的API | |
| 學習曲線 | 1-2天的典型時間 | 通常3-5天 | IronPDF:更快適應 | |
| 平台支持 | 跨平台 | 原生支援,無需額外包 | 完整跨平台支持 | 兩者:現代部署 |
| .NET版本 | .NET 10、9、8、7、6、5、Core 3.1+,Framework 4.6.2+ | .NET 6+,.NET Standard 2.0 | IronPDF:更廣泛的相容性 | |
| 操作系統 | Windows, Linux, macOS, Docker, Azure, AWS | Windows, Linux, macOS | IronPDF:雲端優化 | |
| HTML到PDF | 渲染引擎 | 完整的Chrome V8引擎 | 無內建HTML支持 | IronPDF:HTML功能 |
| CSS3/HTML5支持 | 完整支援 | 需要第三方程式庫 | IronPDF:現代網頁標準 | |
| JavaScript執行 | 完整的JavaScript支持 | 不適用 | IronPDF:動態內容 | |
| 核心功能 | 文字擷取 | 內建ExtractAllText() | 支持有限 | IronPDF:超強提取 |
| 加水印 | 基於HTML/CSS,完整樣式 | 需要手動繪圖 | IronPDF:豐富的水印 | |
| 數位簽名 | 整合的,可視簽名 | Not supported | IronPDF:企業安全性 | |
| 加密 | AES-256,自訂處理器 | 基本加密支持 | IronPDF:高級安全性 | |
| 頁眉/頁腳 | 基於HTML的動態內容 | 手動定位 | IronPDF:動態頁眉 | |
| 性能 | HTML渲染速度 | 0.8-2秒典型(Chrome引擎) | 不適用 | IronPDF:HTML渲染 |
| 大型文件處理 | 優化以便於擴展 | 記憶體高效 | PDFSharpCore:更低的記憶體消耗 | |
| 多執行緒支持 | 本地異步/等待,並行處理 | 執行緒安全操作 | IronPDF:更好的擴展性 | |
| 開發者體驗 | 文件 | 豐富的教程、API文件、影片 | 基本文件 | IronPDF:更好的資源 |
| 程式碼範例 | 100多個即用範例 | 社群範例 | IronPDF:豐富的範例 | |
| IntelliSense支持 | 完整的IntelliSense,XML文件 | 標準IntelliSense | 兩者:IDE整合 | |
| Licensing & Pricing | 許可型別 | 商業的,永久的 | MIT許可證(免費) | PDFSharpCore:無成本 |
| 入門價格 | Lite:$999(1位開發者,1個專案) | 免費 | PDFSharpCore:零成本 | |
| 支援 | 包括24/5工程支援 | 僅社群支援 | IronPDF:專業支援 | |
| 最佳用途 | 用例 | 網頁應用程式,報告,企業 | 簡單的PDF,預算有限的專案 | 依具體情況而定 |
注:PDFSharpCore是一個適合基礎PDF建立的開源程式庫,而IronPDF提供包括HTML渲染和企業支持在內的綜合功能。選擇取決於專案的複雜性和預算限制。
IronPDF和PDFSharpCore簡介
什麼是IronPDF?
IronPDF是一個完整的商業.NET程式庫,設計使開發人員輕鬆生成、編輯和操作PDF。 基於Chrome的渲染引擎,擅長將HTML、CSS和JavaScript內容轉換為像素完美的PDF。 該程式庫提供豐富的功能,包括HTML轉PDF、數位簽名、浮水印、PDF加密和表單管理。
IronPDF支持現代.NET版本,包括.NET 10, 9, 8, 7, 6, 5, Core 3.1+和Framework 4.6.2+,使其適用於新舊應用程式。 其雲端優化的架構確保在Azure、AWS和Docker環境中的無縫部署。
什麼是PDFSharpCore?
PDFSharpCore是一個開源程式庫,作為原始PDFSharp程式庫的.NET Core移植版。 以MIT許可證的方式發布,專注於程式化的PDF建立和基本操作,無需依賴於Windows特定的程式庫。 這使其成為在Linux、macOS和Windows上運行的跨平台專案的絕佳選擇。
雖然PDFSharpCore不提供本地HTML轉PDF功能,但它通過其繪圖API提供對PDF文件建立的精確控制。 開發人員可以通過坐標繪圖命令手動構建PDF文件。
安裝和設置
安裝 IronPDF
要在您的專案中開始使用IronPDF,您可以通過NuGet Package Manager輕鬆安裝。 請按照以下步驟操作:
- 在Visual Studio中打開您的專案。
- 導航到工具 > NuGet套件管理器 > 管理解決方案的NuGet套件。
- 在NuGet管理器中搜尋IronPDF。
- 選擇您的專案,然後點擊安裝將IronPDF新增到您的專案。
透過Visual Studio的NuGet套件管理器介面安裝IronPDF
或者,您可以使用Package Manager控制台通過以下命令安裝IronPDF:
安裝PDFSharpCore
要使用NuGet安裝PDFSharpCore,請按照以下說明進行操作:
- 確保您的Visual Studio專案已打開。
- 轉到工具 > NuGet包管理器 > 管理解決方案的NuGet包。
- 在NuGet包管理器中搜尋PDFSharpCore。
- 選擇您的專案並點擊安裝以合併PDFSharpCore。
通過NuGet包管理器安裝PDFSharpCore
對於偏好使用Package Manager控制台的開發人員,可以通過此命令安裝PDFSharpCore:
建立PDF文件:IronPDF vs PDFSharpCore
IronPDF:基於現代HTML的方法
IronPDF通過利用開發人員已經熟悉的Web技術來革新PDF的建立。 其基於Chrome的渲染引擎確保您的HTML、CSS和JavaScript呈現效果與現代瀏覽器中一致。
帶有高級功能的HTML字串轉PDF
IronPDF的HTML轉PDF轉換功能遠遠超出簡單的文字渲染。 這是一個展示其強大功能的增強範例:
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main(string[] args)
{
// Apply your license key (required for production)
License.LicenseKey = "Your-License-Key";
// Create renderer with optimized settings
var renderer = new ChromePdfRenderer()
{
RenderingOptions = new ChromePdfRenderOptions()
{
// Set margins for professional appearance
MarginTop = 25,
MarginBottom = 25,
MarginLeft = 20,
MarginRight = 20,
// Enable JavaScript execution for dynamic content
EnableJavaScript = true,
// Wait for AJAX/animations to complete
RenderDelay = 500,
// Set paper orientation and size
PaperOrientation = PdfPaperOrientation.Portrait,
PaperSize = PdfPaperSize.A4,
// Enable printing of background colors and images
PrintHtmlBackgrounds = true
}
};
// HTML with Bootstrap styling and charts
string htmlContent = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; }
.chart-container { width: 100%; height: 300px; margin: 20px 0; }
</style>
</head>
<body>
<div class='header text-center'>
<h1>2024 Sales Performance Report</h1>
<p class='lead'>Comprehensive Analysis & Insights</p>
</div>
<div class='container mt-4'>
<div class='row'>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Q1 Performance Metrics</h5>
<table class='table table-striped'>
<thead>
<tr>
<th>Month</th>
<th>Revenue</th>
<th>Growth</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$50,000</td>
<td><span class='badge bg-success'>+12%</span></td>
</tr>
<tr>
<td>February</td>
<td>$55,000</td>
<td><span class='badge bg-success'>+10%</span></td>
</tr>
<tr>
<td>March</td>
<td>$60,000</td>
<td><span class='badge bg-success'>+9%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Revenue Trend</h5>
<canvas id='revenueChart'></canvas>
</div>
</div>
</div>
</div>
<div class='alert alert-info mt-4'>
<strong>Key Insight:</strong> Q1 showed consistent growth across all months,
with total revenue reaching $165,000, representing a 31% increase YoY.
</div>
</div>
<script>
// Create an interactive chart
const ctx = document.getElementById('revenueChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March'],
datasets: [{
label: 'Revenue',
data: [50000, 55000, 60000],
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.1)',
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
</script>
</body>
</html>";
// Render the HTML to PDF
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Add metadata for better document management
pdf.MetaData.Author = "Sales Department";
pdf.MetaData.Title = "Q1 2024 Sales Report";
pdf.MetaData.Subject = "Quarterly Performance Analysis";
pdf.MetaData.Keywords = "sales, performance, Q1, 2024";
pdf.MetaData.CreationDate = DateTime.Now;
// Save the PDF
pdf.SaveAs("sales-report-q1-2024.pdf");
Console.WriteLine("Professional sales report generated successfully!");
}
}Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main(args As String())
' Apply your license key (required for production)
License.LicenseKey = "Your-License-Key"
' Create renderer with optimized settings
Dim renderer = New ChromePdfRenderer() With {
.RenderingOptions = New ChromePdfRenderOptions() With {
' Set margins for professional appearance
.MarginTop = 25,
.MarginBottom = 25,
.MarginLeft = 20,
.MarginRight = 20,
' Enable JavaScript execution for dynamic content
.EnableJavaScript = True,
' Wait for AJAX/animations to complete
.RenderDelay = 500,
' Set paper orientation and size
.PaperOrientation = PdfPaperOrientation.Portrait,
.PaperSize = PdfPaperSize.A4,
' Enable printing of background colors and images
.PrintHtmlBackgrounds = True
}
}
' HTML with Bootstrap styling and charts
Dim htmlContent As String = "
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; }
.chart-container { width: 100%; height: 300px; margin: 20px 0; }
</style>
</head>
<body>
<div class='header text-center'>
<h1>2024 Sales Performance Report</h1>
<p class='lead'>Comprehensive Analysis & Insights</p>
</div>
<div class='container mt-4'>
<div class='row'>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Q1 Performance Metrics</h5>
<table class='table table-striped'>
<thead>
<tr>
<th>Month</th>
<th>Revenue</th>
<th>Growth</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$50,000</td>
<td><span class='badge bg-success'>+12%</span></td>
</tr>
<tr>
<td>February</td>
<td>$55,000</td>
<td><span class='badge bg-success'>+10%</span></td>
</tr>
<tr>
<td>March</td>
<td>$60,000</td>
<td><span class='badge bg-success'>+9%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card'>
<div class='card-body'>
<h5 class='card-title'>Revenue Trend</h5>
<canvas id='revenueChart'></canvas>
</div>
</div>
</div>
</div>
<div class='alert alert-info mt-4'>
<strong>Key Insight:</strong> Q1 showed consistent growth across all months,
with total revenue reaching $165,000, representing a 31% increase YoY.
</div>
</div>
<script>
' Create an interactive chart
const ctx = document.getElementById('revenueChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March'],
datasets: [{
label: 'Revenue',
data: [50000, 55000, 60000],
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.1)',
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
</script>
</body>
</html>"
' Render the HTML to PDF
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
' Add metadata for better document management
pdf.MetaData.Author = "Sales Department"
pdf.MetaData.Title = "Q1 2024 Sales Report"
pdf.MetaData.Subject = "Quarterly Performance Analysis"
pdf.MetaData.Keywords = "sales, performance, Q1, 2024"
pdf.MetaData.CreationDate = DateTime.Now
' Save the PDF
pdf.SaveAs("sales-report-q1-2024.pdf")
Console.WriteLine("Professional sales report generated successfully!")
End Sub
End Class此範例展示了IronPDF的幾個高級功能:
- **Bootstrap整合:**結合流行的CSS框架以專業的樣式呈現
- **JavaScript圖表:**在PDF中呈現動態的Chart.js可視化效果
- **響應式設計:**智能處理響應式佈局
- **元資料管理:**為文件管理系統新增可搜索的元資料
- **渲染延遲:**確保JavaScript內容完全載入後再渲染
ChromePdfRenderer類提供對渲染過程的廣泛控制。 關鍵選項包括:
EnableJavaScript:在渲染之前執行JavaScript程式碼RenderDelay:等待異步內容載入PrintHtmlBackgrounds:保留背景顏色和圖像PaperSize:控制頁面佈局- 專業文件外觀的邊距設置
轉換HTML文件和URL
IronPDF在轉換現有的HTML文件和即時網頁方面也表現出色:
using IronPdf;
class Program
{
static async Task Main(string[] args)
{
License.LicenseKey = "Your-License-Key";
var renderer = new ChromePdfRenderer();
// Convert a local HTML file with external resources
var filePdf = renderer.RenderHtmlFileAsPdf(@"C:\Reports\template.html");
filePdf.SaveAs("from-file.pdf");
// Convert a URL with authentication
renderer.LoginCredentials = new ChromeHttpLoginCredentials()
{
Username = "user@example.com",
Password = "secure-password"
};
// Render a password-protected page
var urlPdf = await renderer.RenderUrlAsPdfAsync("https://secure.example.com/reports");
urlPdf.SaveAs("secure-report.pdf");
}
}Imports IronPdf
Module Program
Async Function Main(ByVal args As String()) As Task
License.LicenseKey = "Your-License-Key"
Dim renderer As New ChromePdfRenderer()
' Convert a local HTML file with external resources
Dim filePdf = renderer.RenderHtmlFileAsPdf("C:\Reports\template.html")
filePdf.SaveAs("from-file.pdf")
' Convert a URL with authentication
renderer.LoginCredentials = New ChromeHttpLoginCredentials() With {
.Username = "user@example.com",
.Password = "secure-password"
}
' Render a password-protected page
Dim urlPdf = Await renderer.RenderUrlAsPdfAsync("https://secure.example.com/reports")
urlPdf.SaveAs("secure-report.pdf")
End Function
End ModulePDFSharpCore:手動文件構建
PDFSharpCore採取了一種根本不同的方法,需要開發人員使用繪圖命令手動構建PDF文件。 雖然這提供了精確的控制,但對於複雜佈局需要大量的程式碼。
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using System;
class Program
{
static void Main()
{
// Create a new PDF document
var document = new PdfDocument();
document.Info.Title = "Sales Report Q1 2024";
document.Info.Author = "Sales Department";
// Add a page
var page = document.AddPage();
page.Size = PdfSharpCore.PageSize.A4;
// Create graphics object for drawing
var gfx = XGraphics.FromPdfPage(page);
// Define fonts
var titleFont = new XFont("Arial", 24, XFontStyle.Bold);
var headingFont = new XFont("Arial", 14, XFontStyle.Bold);
var normalFont = new XFont("Arial", 11, XFontStyle.Regular);
// Draw title with gradient-like effect (manual implementation)
var titleBrush = new XLinearGradientBrush(
new XPoint(0, 0),
new XPoint(page.Width, 0),
XColors.DarkBlue,
XColors.Purple
);
gfx.DrawRectangle(titleBrush, 0, 0, page.Width, 80);
gfx.DrawString("2024 Sales Performance Report",
titleFont, XBrushes.White,
new XRect(0, 20, page.Width, 40),
XStringFormats.TopCenter);
// Draw table manually
double yPosition = 120;
double margin = 50;
double columnWidth = (page.Width - 2 * margin) / 3;
// Table header
gfx.DrawRectangle(XBrushes.LightGray, margin, yPosition, page.Width - 2 * margin, 25);
gfx.DrawString("Month", headingFont, XBrushes.Black,
new XRect(margin, yPosition, columnWidth, 25),
XStringFormats.Center);
gfx.DrawString("Revenue", headingFont, XBrushes.Black,
new XRect(margin + columnWidth, yPosition, columnWidth, 25),
XStringFormats.Center);
gfx.DrawString("Growth", headingFont, XBrushes.Black,
new XRect(margin + 2 * columnWidth, yPosition, columnWidth, 25),
XStringFormats.Center);
// Table data
string[,] data = {
{ "January", "$50,000", "+12%" },
{ "February", "$55,000", "+10%" },
{ "March", "$60,000", "+9%" }
};
yPosition += 25;
for (int i = 0; i < 3; i++)
{
// Alternate row colors
if (i % 2 == 0)
{
gfx.DrawRectangle(XBrushes.WhiteSmoke, margin, yPosition, page.Width - 2 * margin, 20);
}
for (int j = 0; j < 3; j++)
{
gfx.DrawString(data[i, j], normalFont, XBrushes.Black,
new XRect(margin + j * columnWidth, yPosition, columnWidth, 20),
XStringFormats.Center);
}
yPosition += 20;
}
// Draw a simple line chart (very basic implementation)
yPosition += 40;
gfx.DrawString("Revenue Trend", headingFont, XBrushes.Black,
new XRect(margin, yPosition, page.Width - 2 * margin, 25),
XStringFormats.TopLeft);
// Chart area
yPosition += 30;
double chartHeight = 150;
double chartWidth = page.Width - 2 * margin;
// Draw axes
gfx.DrawLine(XPens.Black, margin, yPosition + chartHeight, margin + chartWidth, yPosition + chartHeight);
gfx.DrawLine(XPens.Black, margin, yPosition, margin, yPosition + chartHeight);
// Plot points (simplified)
double[] revenues = { 50000, 55000, 60000 };
double maxRevenue = 65000;
double xStep = chartWidth / 3;
for (int i = 0; i < revenues.Length; i++)
{
double x = margin + (i + 0.5) * xStep;
double y = yPosition + chartHeight - (revenues[i] / maxRevenue * chartHeight);
// Draw point
gfx.DrawEllipse(XBrushes.Blue, x - 3, y - 3, 6, 6);
// Draw connecting lines
if (i > 0)
{
double prevX = margin + (i - 0.5) * xStep;
double prevY = yPosition + chartHeight - (revenues[i - 1] / maxRevenue * chartHeight);
gfx.DrawLine(new XPen(XColors.Blue, 2), prevX, prevY, x, y);
}
// Labels
gfx.DrawString($"${revenues[i]:N0}", normalFont, XBrushes.Black,
new XRect(x - 30, y - 20, 60, 15),
XStringFormats.TopCenter);
}
// Save the document
document.Save("pdfsharp-sales-report.pdf");
Console.WriteLine("PDF created with PDFSharpCore");
}
}Imports PdfSharpCore.Drawing
Imports PdfSharpCore.Pdf
Imports System
Class Program
Shared Sub Main()
' Create a new PDF document
Dim document As New PdfDocument()
document.Info.Title = "Sales Report Q1 2024"
document.Info.Author = "Sales Department"
' Add a page
Dim page As PdfPage = document.AddPage()
page.Size = PdfSharpCore.PageSize.A4
' Create graphics object for drawing
Dim gfx As XGraphics = XGraphics.FromPdfPage(page)
' Define fonts
Dim titleFont As New XFont("Arial", 24, XFontStyle.Bold)
Dim headingFont As New XFont("Arial", 14, XFontStyle.Bold)
Dim normalFont As New XFont("Arial", 11, XFontStyle.Regular)
' Draw title with gradient-like effect (manual implementation)
Dim titleBrush As New XLinearGradientBrush(New XPoint(0, 0), New XPoint(page.Width, 0), XColors.DarkBlue, XColors.Purple)
gfx.DrawRectangle(titleBrush, 0, 0, page.Width, 80)
gfx.DrawString("2024 Sales Performance Report", titleFont, XBrushes.White, New XRect(0, 20, page.Width, 40), XStringFormats.TopCenter)
' Draw table manually
Dim yPosition As Double = 120
Dim margin As Double = 50
Dim columnWidth As Double = (page.Width - 2 * margin) / 3
' Table header
gfx.DrawRectangle(XBrushes.LightGray, margin, yPosition, page.Width - 2 * margin, 25)
gfx.DrawString("Month", headingFont, XBrushes.Black, New XRect(margin, yPosition, columnWidth, 25), XStringFormats.Center)
gfx.DrawString("Revenue", headingFont, XBrushes.Black, New XRect(margin + columnWidth, yPosition, columnWidth, 25), XStringFormats.Center)
gfx.DrawString("Growth", headingFont, XBrushes.Black, New XRect(margin + 2 * columnWidth, yPosition, columnWidth, 25), XStringFormats.Center)
' Table data
Dim data As String(,) = {{"January", "$50,000", "+12%"}, {"February", "$55,000", "+10%"}, {"March", "$60,000", "+9%"}}
yPosition += 25
For i As Integer = 0 To 2
' Alternate row colors
If i Mod 2 = 0 Then
gfx.DrawRectangle(XBrushes.WhiteSmoke, margin, yPosition, page.Width - 2 * margin, 20)
End If
For j As Integer = 0 To 2
gfx.DrawString(data(i, j), normalFont, XBrushes.Black, New XRect(margin + j * columnWidth, yPosition, columnWidth, 20), XStringFormats.Center)
Next
yPosition += 20
Next
' Draw a simple line chart (very basic implementation)
yPosition += 40
gfx.DrawString("Revenue Trend", headingFont, XBrushes.Black, New XRect(margin, yPosition, page.Width - 2 * margin, 25), XStringFormats.TopLeft)
' Chart area
yPosition += 30
Dim chartHeight As Double = 150
Dim chartWidth As Double = page.Width - 2 * margin
' Draw axes
gfx.DrawLine(XPens.Black, margin, yPosition + chartHeight, margin + chartWidth, yPosition + chartHeight)
gfx.DrawLine(XPens.Black, margin, yPosition, margin, yPosition + chartHeight)
' Plot points (simplified)
Dim revenues() As Double = {50000, 55000, 60000}
Dim maxRevenue As Double = 65000
Dim xStep As Double = chartWidth / 3
For i As Integer = 0 To revenues.Length - 1
Dim x As Double = margin + (i + 0.5) * xStep
Dim y As Double = yPosition + chartHeight - (revenues(i) / maxRevenue * chartHeight)
' Draw point
gfx.DrawEllipse(XBrushes.Blue, x - 3, y - 3, 6, 6)
' Draw connecting lines
If i > 0 Then
Dim prevX As Double = margin + (i - 0.5) * xStep
Dim prevY As Double = yPosition + chartHeight - (revenues(i - 1) / maxRevenue * chartHeight)
gfx.DrawLine(New XPen(XColors.Blue, 2), prevX, prevY, x, y)
End If
' Labels
gfx.DrawString($"${revenues(i):N0}", normalFont, XBrushes.Black, New XRect(x - 30, y - 20, 60, 15), XStringFormats.TopCenter)
Next
' Save the document
document.Save("pdfsharp-sales-report.pdf")
Console.WriteLine("PDF created with PDFSharpCore")
End Sub
End Class如您所見,使用PDFSharpCore建立即使是中等複雜的文件也需要:
- 每個元素的手動定位
- 複雜的佈局計算
- 不支持HTML或CSS
- 手動實現圖表和圖形
- 為相同結果編寫更多程式碼
使用PDFSharpCore進行HTML轉PDF
由於PDFSharpCore不原生支持HTML轉PDF,開發人員必須使用第三方程式庫。 常見的選擇是將PDFSharpCore與HtmlRenderer結合使用:
using PdfSharpCore.Pdf;
using TheArtOfDev.HtmlRenderer.PdfSharp;
var document = new PdfDocument();
string htmlContent = File.ReadAllText("template.html");
// Note: HtmlRenderer has limited CSS support
PdfGenerator.AddPdfPages(document, htmlContent, PdfSharpCore.PageSize.A4);
document.Save("from-html.pdf");Imports PdfSharpCore.Pdf
Imports TheArtOfDev.HtmlRenderer.PdfSharp
Private document = New PdfDocument()
Private htmlContent As String = File.ReadAllText("template.html")
' Note: HtmlRenderer has limited CSS support
PdfGenerator.AddPdfPages(document, htmlContent, PdfSharpCore.PageSize.A4)
document.Save("from-html.pdf")但是,這種方法有顯著的限制:
- 有限的CSS3支持(沒有Flexbox,沒有CSS Grid,沒有現代框架支持)
- 不支持JavaScript執行
- 無法處理現代網頁功能
- 與瀏覽器相比渲染不一致
現代CSS框架支持:Bootstrap及其他
開發需要從Web內容生成PDF的應用程式時,Bootstrap和現代CSS框架支持至關重要。 大多數Web應用程式使用這些框架以保持設計一致性,能夠在不修改的情況下將這些介面轉換為PDF顯著減少了開發時間。
IronPDF:完整的Bootstrap與CSS框架支援
- **Bootstrap 5:**完全的flexbox版面引擎、CSS Grid、實用類別和所有元件系統
- **Bootstrap 4:**完整的卡片組件、導航、Flex工具及響應式類
- **Tailwind CSS:**所有工具類的準確渲染
- Foundation: 完整的網格系統和組件庫
- **現代CSS3:**Flexbox,CSS Grid,自訂屬性,動畫,過渡和變換
現實證明:IronPDF完美渲染Bootstrap主頁及所有官方範本。
程式碼範例:專案進度儀表板
using IronPdf;
// Set yourIronPDFlicense key
IronPdf.License.LicenseKey = "License-Key goes here";
var renderer = new ChromePdfRenderer();
string bootstrapProgress = @"
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
<style>
.project-card {
transition: all 0.3s ease;
border-left: 4px solid transparent;
}
.project-card.active { border-left-color: #0d6efd; }
.progress-label { font-size: 0.75rem; font-weight: 600; }
</style>
</head>
<body>
<div class='container my-5'>
<div class='d-flex justify-content-between align-items-center mb-4'>
<div>
<h1 class='display-6 mb-1'>Project Portfolio Status</h1>
<p class='text-muted mb-0'>Q1 2025 Development Pipeline</p>
</div>
<div>
<span class='badge bg-success fs-6'>8 Active Projects</span>
</div>
</div>
<div class='row g-4 mb-4'>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-primary mb-2'>72%</div>
<h6 class='text-muted text-uppercase mb-0'>Overall Progress</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-success mb-2'>5</div>
<h6 class='text-muted text-uppercase mb-0'>On Track</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-warning mb-2'>2</div>
<h6 class='text-muted text-uppercase mb-0'>At Risk</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-danger mb-2'>1</div>
<h6 class='text-muted text-uppercase mb-0'>Delayed</h6>
</div>
</div>
</div>
</div>
<div class='card shadow-sm mb-4'>
<div class='card-header bg-primary text-white'>
<h5 class='mb-0'>Active Projects</h5>
</div>
<div class='card-body p-0'>
<div class='list-group list-group-flush'>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>E-Commerce Platform Redesign</h6>
<small class='text-muted'>Lead: Sarah Chen | Due: Apr 15, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-primary'>85%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-primary' role='progressbar' style='width: 85%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Frontend: 90%</span>
<span class='badge bg-light text-dark'>Backend: 80%</span>
<span class='badge bg-light text-dark'>Testing: 85%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Mobile App Integration</h6>
<small class='text-muted'>Lead: Marcus Johnson | Due: Mar 30, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-success'>92%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-success' role='progressbar' style='width: 92%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>iOS: 95%</span>
<span class='badge bg-light text-dark'>Android: 90%</span>
<span class='badge bg-light text-dark'>API: 100%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Customer Analytics Dashboard</h6>
<small class='text-muted'>Lead: Emily Rodriguez | Due: Apr 22, 2025</small>
</div>
<span class='badge bg-warning text-dark'>At Risk</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-warning'>58%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-warning' role='progressbar' style='width: 58%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Data Pipeline: 65%</span>
<span class='badge bg-light text-dark'>UI: 50%</span>
<span class='badge bg-light text-dark'>Reports: 45%</span>
</div>
<div class='alert alert-warning mt-2 mb-0 py-2'>
<small><strong>Issue:</strong> Resource constraints affecting timeline. Review scheduled for next week.</small>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Security Infrastructure Upgrade</h6>
<small class='text-muted'>Lead: David Kim | Due: Mar 25, 2025</small>
</div>
<span class='badge bg-danger'>Delayed</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-danger'>42%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-danger' role='progressbar' style='width: 42%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Authentication: 60%</span>
<span class='badge bg-light text-dark'>加密: 40%</span>
<span class='badge bg-light text-dark'>Audit Logs: 25%</span>
</div>
<div class='alert alert-danger mt-2 mb-0 py-2'>
<small><strong>Critical:</strong> 7 days behind schedule. Additional resources allocated. Daily standup required.</small>
</div>
</div>
</div>
</div>
</div>
<div class='row g-4'>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Sprint Velocity</h5>
</div>
<div class='card-body'>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Current Sprint</span>
<strong>42 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-success' style='width: 84%'>84% Complete</div>
</div>
</div>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Previous Sprint</span>
<strong>38 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-info' style='width: 100%'>Completed</div>
</div>
</div>
<div class='mb-0'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Average Velocity</span>
<strong>40 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-primary' style='width: 100%'>Baseline</div>
</div>
</div>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Team Capacity</h5>
</div>
<div class='card-body'>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Frontend Team</h6>
<small class='text-muted'>6 developers</small>
</div>
<span class='badge bg-success'>92% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Backend Team</h6>
<small class='text-muted'>5 developers</small>
</div>
<span class='badge bg-success'>88% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>QA Team</h6>
<small class='text-muted'>3 testers</small>
</div>
<span class='badge bg-warning text-dark'>105% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-0'>
<div>
<h6 class='mb-0'>DevOps Team</h6>
<small class='text-muted'>2 engineers</small>
</div>
<span class='badge bg-danger'>110% Utilized</span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(bootstrapProgress);
pdf.SaveAs("project-progress.pdf");Imports IronPdf
' Set your IronPDF license key
IronPdf.License.LicenseKey = "License-Key goes here"
Dim renderer As New ChromePdfRenderer()
Dim bootstrapProgress As String = "
<!DOCTYPE html>
<html>
<head>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
<style>
.project-card {
transition: all 0.3s ease;
border-left: 4px solid transparent;
}
.project-card.active { border-left-color: #0d6efd; }
.progress-label { font-size: 0.75rem; font-weight: 600; }
</style>
</head>
<body>
<div class='container my-5'>
<div class='d-flex justify-content-between align-items-center mb-4'>
<div>
<h1 class='display-6 mb-1'>Project Portfolio Status</h1>
<p class='text-muted mb-0'>Q1 2025 Development Pipeline</p>
</div>
<div>
<span class='badge bg-success fs-6'>8 Active Projects</span>
</div>
</div>
<div class='row g-4 mb-4'>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-primary mb-2'>72%</div>
<h6 class='text-muted text-uppercase mb-0'>Overall Progress</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-success mb-2'>5</div>
<h6 class='text-muted text-uppercase mb-0'>On Track</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-warning mb-2'>2</div>
<h6 class='text-muted text-uppercase mb-0'>At Risk</h6>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center shadow-sm'>
<div class='card-body'>
<div class='display-4 text-danger mb-2'>1</div>
<h6 class='text-muted text-uppercase mb-0'>Delayed</h6>
</div>
</div>
</div>
</div>
<div class='card shadow-sm mb-4'>
<div class='card-header bg-primary text-white'>
<h5 class='mb-0'>Active Projects</h5>
</div>
<div class='card-body p-0'>
<div class='list-group list-group-flush'>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>E-Commerce Platform Redesign</h6>
<small class='text-muted'>Lead: Sarah Chen | Due: Apr 15, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-primary'>85%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-primary' role='progressbar' style='width: 85%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Frontend: 90%</span>
<span class='badge bg-light text-dark'>Backend: 80%</span>
<span class='badge bg-light text-dark'>Testing: 85%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Mobile App Integration</h6>
<small class='text-muted'>Lead: Marcus Johnson | Due: Mar 30, 2025</small>
</div>
<span class='badge bg-success'>On Track</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-success'>92%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-success' role='progressbar' style='width: 92%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>iOS: 95%</span>
<span class='badge bg-light text-dark'>Android: 90%</span>
<span class='badge bg-light text-dark'>API: 100%</span>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Customer Analytics Dashboard</h6>
<small class='text-muted'>Lead: Emily Rodriguez | Due: Apr 22, 2025</small>
</div>
<span class='badge bg-warning text-dark'>At Risk</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-warning'>58%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-warning' role='progressbar' style='width: 58%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Data Pipeline: 65%</span>
<span class='badge bg-light text-dark'>UI: 50%</span>
<span class='badge bg-light text-dark'>Reports: 45%</span>
</div>
<div class='alert alert-warning mt-2 mb-0 py-2'>
<small><strong>Issue:</strong> Resource constraints affecting timeline. Review scheduled for next week.</small>
</div>
</div>
<div class='list-group-item'>
<div class='d-flex justify-content-between align-items-start mb-3'>
<div>
<h6 class='mb-1'>Security Infrastructure Upgrade</h6>
<small class='text-muted'>Lead: David Kim | Due: Mar 25, 2025</small>
</div>
<span class='badge bg-danger'>Delayed</span>
</div>
<div class='mb-2'>
<div class='d-flex justify-content-between align-items-center mb-1'>
<span class='progress-label text-muted'>COMPLETION</span>
<span class='progress-label text-danger'>42%</span>
</div>
<div class='progress' style='height: 8px;'>
<div class='progress-bar bg-danger' role='progressbar' style='width: 42%'></div>
</div>
</div>
<div class='d-flex gap-2 flex-wrap'>
<span class='badge bg-light text-dark'>Authentication: 60%</span>
<span class='badge bg-light text-dark'>加密: 40%</span>
<span class='badge bg-light text-dark'>Audit Logs: 25%</span>
</div>
<div class='alert alert-danger mt-2 mb-0 py-2'>
<small><strong>Critical:</strong> 7 days behind schedule. Additional resources allocated. Daily standup required.</small>
</div>
</div>
</div>
</div>
</div>
<div class='row g-4'>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Sprint Velocity</h5>
</div>
<div class='card-body'>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Current Sprint</span>
<strong>42 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-success' style='width: 84%'>84% Complete</div>
</div>
</div>
<div class='mb-3'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Previous Sprint</span>
<strong>38 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-info' style='width: 100%'>Completed</div>
</div>
</div>
<div class='mb-0'>
<div class='d-flex justify-content-between mb-1'>
<span class='text-muted'>Average Velocity</span>
<strong>40 Story Points</strong>
</div>
<div class='progress' style='height: 20px;'>
<div class='progress-bar bg-primary' style='width: 100%'>Baseline</div>
</div>
</div>
</div>
</div>
</div>
<div class='col-md-6'>
<div class='card shadow-sm'>
<div class='card-header bg-white'>
<h5 class='mb-0'>Team Capacity</h5>
</div>
<div class='card-body'>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Frontend Team</h6>
<small class='text-muted'>6 developers</small>
</div>
<span class='badge bg-success'>92% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>Backend Team</h6>
<small class='text-muted'>5 developers</small>
</div>
<span class='badge bg-success'>88% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-3'>
<div>
<h6 class='mb-0'>QA Team</h6>
<small class='text-muted'>3 testers</small>
</div>
<span class='badge bg-warning text-dark'>105% Utilized</span>
</div>
<div class='d-flex justify-content-between align-items-center mb-0'>
<div>
<h6 class='mb-0'>DevOps Team</h6>
<small class='text-muted'>2 engineers</small>
</div>
<span class='badge bg-danger'>110% Utilized</span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>"
Dim pdf = renderer.RenderHtmlAsPdf(bootstrapProgress)
pdf.SaveAs("project-progress.pdf")**輸出:**使用Bootstrap 5的Flexbox佈局、進度條組件、徽章工具、響應式卡片系統和警報組件生成的專業專案管理PDF——所有這些都具有完美的對齊、間距和顏色準確性。
PDFSharpCore:無本地HTML支持
PDFSharpCore無本地HTML渲染引擎。 該程式庫專門用於低階PDF操縱和繪圖操作:
- **無Bootstrap支持:**無法處理HTML/CSS框架
- **無Flexbox或CSS Grid:**無任何CSS渲染能力
- **僅手動構建:**需要使用坐標API繪製文字、圖形和圖像
- **需要外部工具:**必須使用第三方HTML渲染或轉換服務
HtmlRenderer整合(第三方)僅提供基本HTML支持,限制多多——無Flexbox,無CSS Grid,無現代框架支持。
**對開發影響:**團隊要麼放棄基於HTML的工作流程,要麼整合多個工具(PDFSharpCore+外部HTML渲染器),從而增加了複雜性、維護負擔和程式庫版本間的潛在相容性問題。
有關詳細的Bootstrap框架相容性和CSS3渲染能力,請參閱Bootstrap與Flexbox CSS指南。
高級功能比較
文字提取
提取文字以進行索引、分析或轉換是最常見的PDF操作之一。 這是兩種程式庫如何處理此任務的方法:
IronPDF文字提取
IronPDF提供強大的文字提取能力,擁有簡單的API:
using IronPdf;
// Extract all text from a PDF
var pdf = PdfDocument.FromFile("report.pdf");
string allText = pdf.ExtractAllText();
// Extract text from specific pages
for (int i = 0; i < pdf.PageCount; i++)
{
string pageText = pdf.ExtractTextFromPage(i);
Console.WriteLine($"Page {i + 1}: {pageText.Substring(0, Math.Min(100, pageText.Length))}...");
}
// Extract text from a specific region
var pageIndex = 0;
var region = new Rectangle(50, 50, 200, 100); // x, y, width, height
string regionText = pdf.ExtractTextFromPage(pageIndex, region);Imports IronPdf
' Extract all text from a PDF
Private pdf = PdfDocument.FromFile("report.pdf")
Private allText As String = pdf.ExtractAllText()
' Extract text from specific pages
For i As Integer = 0 To pdf.PageCount - 1
Dim pageText As String = pdf.ExtractTextFromPage(i)
Console.WriteLine($"Page {i + 1}: {pageText.Substring(0, Math.Min(100, pageText.Length))}...")
Next i
' Extract text from a specific region
Dim pageIndex = 0
Dim region = New Rectangle(50, 50, 200, 100) ' x, y, width, height
Dim regionText As String = pdf.ExtractTextFromPage(pageIndex, region)PDFSharpCore文字提取
PDFSharpCore原生文字提取能力有限。 正如在比較文章中提到的,它常常會產生碎片或不完整的結果:
// PDFSharpCore doesn't have reliable text extraction
// This is a significant limitation for many use cases' PDFSharpCore doesn't have reliable text extraction
' This is a significant limitation for many use cases浮水印
PDF浮水印對於品牌和文件安全性至關重要。
IronPDF浮水印
using IronPdf;
var pdf = PdfDocument.FromFile("document.pdf");
// HTML-based watermark with full CSS support
string watermarkHtml = @"
<div style='
font-size: 48px;
color: rgba(255, 0, 0, 0.3);
transform: rotate(-45deg);
text-align: center;
font-weight: bold;
'>
CONFIDENTIAL
</div>";
pdf.ApplyWatermark(watermarkHtml, 50, VerticalAlignment.Middle, HorizontalAlignment.Center);
// Image watermark
pdf.ApplyWatermark("logo.png", 30, VerticalAlignment.Bottom, HorizontalAlignment.Right);
pdf.SaveAs("watermarked.pdf");Imports IronPdf
Private pdf = PdfDocument.FromFile("document.pdf")
' HTML-based watermark with full CSS support
Private watermarkHtml As String = "
<div style='
font-size: 48px;
color: rgba(255, 0, 0, 0.3);
transform: rotate(-45deg);
text-align: center;
font-weight: bold;
'>
CONFIDENTIAL
</div>"
pdf.ApplyWatermark(watermarkHtml, 50, VerticalAlignment.Middle, HorizontalAlignment.Center)
' Image watermark
pdf.ApplyWatermark("logo.png", 30, VerticalAlignment.Bottom, HorizontalAlignment.Right)
pdf.SaveAs("watermarked.pdf")PDFSharpCore浮水印
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
var document = PdfReader.Open("document.pdf", PdfDocumentOpenMode.Modify);
foreach (var page in document.Pages)
{
var gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append);
// Create watermark font
var font = new XFont("Arial", 48);
// Calculate rotation
gfx.TranslateTransform(page.Width / 2, page.Height / 2);
gfx.RotateTransform(-45);
// Draw watermark
var size = gfx.MeasureString("CONFIDENTIAL", font);
gfx.DrawString("CONFIDENTIAL", font,
new XSolidBrush(XColor.FromArgb(128, 255, 0, 0)),
new XRect(-size.Width / 2, -size.Height / 2, size.Width, size.Height),
XStringFormats.Center);
}
document.Save("watermarked-pdfsharp.pdf");Imports PdfSharpCore.Drawing
Imports PdfSharpCore.Pdf
Imports PdfSharpCore.Pdf.IO
Dim document = PdfReader.Open("document.pdf", PdfDocumentOpenMode.Modify)
For Each page In document.Pages
Dim gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append)
' Create watermark font
Dim font = New XFont("Arial", 48)
' Calculate rotation
gfx.TranslateTransform(page.Width / 2, page.Height / 2)
gfx.RotateTransform(-45)
' Draw watermark
Dim size = gfx.MeasureString("CONFIDENTIAL", font)
gfx.DrawString("CONFIDENTIAL", font,
New XSolidBrush(XColor.FromArgb(128, 255, 0, 0)),
New XRect(-size.Width / 2, -size.Height / 2, size.Width, size.Height),
XStringFormats.Center)
Next
document.Save("watermarked-pdfsharp.pdf")數位簽名
數位簽名確保文件的真實性和完整性。
IronPDF數位簽名
using IronPdf;
using IronPdf.Signing;
var pdf = PdfDocument.FromFile("contract.pdf");
// Create a signature with certificate
var signature = new PdfSignature("certificate.pfx", "password")
{
SigningContact = "legal@company.com",
SigningLocation = "New York, NY",
SigningReason = "Contract Approval"
};
// Add visual signature
var signatureImage = new PdfSignature("certificate.pfx", "password")
{
SignatureImage = new PdfSignatureImage("signature.png", 0, 0, 200, 100)
};
// Apply signature to the last page
pdf.Sign(signature);
pdf.SaveAs("signed-contract.pdf");Imports IronPdf
Imports IronPdf.Signing
Private pdf = PdfDocument.FromFile("contract.pdf")
' Create a signature with certificate
Private signature = New PdfSignature("certificate.pfx", "password") With {
.SigningContact = "legal@company.com",
.SigningLocation = "New York, NY",
.SigningReason = "Contract Approval"
}
' Add visual signature
Private signatureImage = New PdfSignature("certificate.pfx", "password") With {.SignatureImage = New PdfSignatureImage("signature.png", 0, 0, 200, 100)}
' Apply signature to the last page
pdf.Sign(signature)
pdf.SaveAs("signed-contract.pdf")PDFSharpCore數位簽名
PDFSharpCore不支援數位簽名原生功能,這是需求文件安全的業務應用程式的一個重大限制。
表單處理
處理PDF表單對於互動式文件至關重要。
IronPDF表單處理
using IronPdf;
// Create a form from HTML
var html = @"
<form>
<label>Name: <input type='text' name='fullName' required></label><br>
<label>Email: <input type='email' name='email' required></label><br>
<label>Subscribe: <input type='checkbox' name='subscribe' value='yes'></label><br>
<label>
Plan:
<select name='plan'>
<option value='basic'>Basic</option>
<option value='pro'>Professional</option>
<option value='enterprise'>Enterprise</option>
</select>
</label>
</form>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Fill existing form
var filledPdf = PdfDocument.FromFile("application-form.pdf");
filledPdf.Form.FindFormField("fullName").Value = "John Doe";
filledPdf.Form.FindFormField("email").Value = "john@example.com";
filledPdf.Form.FindFormField("subscribe").Value = "yes";
filledPdf.SaveAs("completed-application.pdf");Imports IronPdf
' Create a form from HTML
Private html = "
<form>
<label>Name: <input type='text' name='fullName' required></label><br>
<label>Email: <input type='email' name='email' required></label><br>
<label>Subscribe: <input type='checkbox' name='subscribe' value='yes'></label><br>
<label>
Plan:
<select name='plan'>
<option value='basic'>Basic</option>
<option value='pro'>Professional</option>
<option value='enterprise'>Enterprise</option>
</select>
</label>
</form>"
Private renderer = New ChromePdfRenderer()
Private pdf = renderer.RenderHtmlAsPdf(html)
' Fill existing form
Private filledPdf = PdfDocument.FromFile("application-form.pdf")
filledPdf.Form.FindFormField("fullName").Value = "John Doe"
filledPdf.Form.FindFormField("email").Value = "john@example.com"
filledPdf.Form.FindFormField("subscribe").Value = "yes"
filledPdf.SaveAs("completed-application.pdf")性能基準
以下是基於典型使用模式的性能比較:
HTML轉PDF渲染
| 測試案例 | IronPDF | PDFSharpCore(搭配HtmlRenderer) |
|---|---|---|
| 簡單HTML (1頁) | 快速(Chrome引擎開銷) | 對於微不足道的輸出更快 |
| 複雜的HTML與CSS3 | 完整渲染,準確輸出 | 經常失敗或渲染不正確 |
| JavaScript圖表 | 完全的JavaScript執行 | 不支援 |
| 大型文件批處理 | 優化的異步/並行處理 | 更低的記憶體占用 |
| 記憶體使用 | 更高(Chrome引擎) | 更低(輕量級程式庫) |
關鍵性能洞察
-
IronPDF精於:
- 複雜的HTML渲染,具有完整的瀏覽器相容性
- 並行處理批量操作
- 在不同內容型別上的穩定性能
- 異步操作以獲得更好的可擴展性
-
PDFSharpCore更適合:
- 簡單的程式化PDF建立
- 更低的記憶體占用
- 基本文件修改
現實世界性能範例
//IronPDF- Batch processing with parallel execution
using IronPdf;
using System.Threading.Tasks;
class BatchProcessor
{
public static async Task ProcessInvoicesAsync(List<string> htmlInvoices)
{
var renderer = new ChromePdfRenderer();
// Process multiple PDFs in parallel
var tasks = htmlInvoices.Select(async (html, index) =>
{
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
await pdf.SaveAsAsync($"invoice-{index}.pdf");
});
await Task.WhenAll(tasks);
}
}
現實世界的應用範例
何時選擇IronPDF
IronPDF非常適合:
-
網頁應用程式整合
- 將動態Web內容轉換為PDF
- 從Web儀表板生成報告
- 從HTML範本建立發票
-
企業文件管理
- 使用數位簽名實現文件工作流程
- 建立安全加密的PDF來保護敏感資料
- 批量處理大量文件
-
SaaS應用程式
- 多租戶PDF生成
- 在Azure/AWS上的雲端本地佈署
- 高效的異步処理
-
複雜報告
- 視圖和圖表的財務報表
- 含豐富多媒體的市場材料
- 加強顯示程式碼的技術文件
何時選擇PDFSharpCore
PDFSharpCore適用於:
-
預算有限的專案
- 無需授權預算的開源專案
- 簡單的PDF生成需求
- 學術或個人專案
-
基本PDF操作
- 建立簡單的基於文字的PDF
- 基本的文件合併
- 新增簡單圖像或形狀
-
輕量級應用程式
- 記憶體有限的嵌入式系統
- 簡單的命令行工具
- 具有最低依賴的微服務
授權和定價
###IronPDF授權
IronPDF提供靈活的授權選項(2026年4月價格):
- Lite License: $999(1 開發者,1 地點,1 專案)
- Plus License: $1,499(3 開發者,3 地點,3 專案)
- Professional License: $2,399(10 開發者,10 地點,10 專案)
- **免費試用:**30 天功能齊全的試用
額外收益:
- 永續授權(一次性購買)
- 免版稅再分發可用
- 包括24/5工程支援
- 一年免費更新
- 可供選擇的Iron Suite套件以獲得額外的節省
PDFSharpCore授權
PDFSharpCore在MIT許可證下完全免費:
- 無授權費用
- 無商業使用限制
- 僅社群支援
- 缺乏保證的更新或錯誤修正
開發者體驗
文件和資源
IronPDF提供:
PDFSharpCore提供:
- 基本的GitHub文件
- 社群範例
- 有限的官方教程
支援比較
| 支援型別 | IronPDF | PDFSharpCore |
|---|---|---|
| 專業支援 | 包含24/5 | None |
| 響應時間 | 24-48小時 | 社群依賴 |
| 直接工程存取 | 是 | 否 |
| 錯誤修正保證 | 是 | 否 |
結論
IronPDF和PDFSharpCore都在.NET PDF生態系統中發揮著重要作用,但它們面向不同的需求和使用案例。
選擇IronPDF當:
- 您需要具有完整CSS3和JavaScript支持的強大HTML轉PDF功能
- 您的專案需要數位簽名、加密或表單處理等高級功能
- 您正在開發企業或商業應用程式
- 您重視全面的文件和專業支援
- 性能和可靠性是關鍵
- 您需要雲端就緒的佈署選項
選擇PDFSharpCore的理由:
- 您在進行預算受限或開源項目
- 您的PDF需求簡單,不需要HTML渲染
- 您喜歡對PDF構建進行手動控制
- 記憶體使用是關鍵問題
- 您習慣於社群支援
IronPDF的現代PDF生成方法,結合其豐富的功能集和出色的支援,成為大多數專業應用程式的最佳選擇。 雖然需要授權投資,但開發過程中節省的時間和獲得的可靠性常常證明對於商業專案的成本是值得的。
準備好體驗不同了嗎? 開始您的IronPDF免費30天試用,看看它如何改變您的PDF生成工作流程。 憑藉全面的文件、響應迅速的支援和功能豐富的API,IronPDF使開發者能夠輕鬆建立專業PDF。

Jacob Mellor是Iron Software的首席技術官,一位在C# PDF技術上開創先河的遠見工程師。作為Iron Software核心程式碼庫的原開發者,他從創立以來就一直在塑造公司的產品架構,與首席執行官Cameron Rimington一起將公司轉變為服務於NASA、特斯拉和全球政府公司的50多名人員的公司。
相關文章


