.NET操作PDF的完整指南
作者:墨夶
在.NET 开发中,常常需要对 PDF 文档进行各种操作,以下是一些常见的方法和技术要点,文章通过代码示例讲解的非常详细,需要的朋友可以参考下
本文将通过真实项目案例,手把手教你:
- 用iTextSharp实现高效读写PDF
- 用PDFsharp完成跨平台PDF生成
- 用PdfiumViewer实现无插件PDF预览
- 用PDFiumCore处理复杂PDF渲染
- 避坑指南:内存泄漏、权限异常、性能瓶颈的解决方案
第一章:iTextSharp——PDF操作的瑞士军刀
1.1 读取PDF文本内容
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
public class PdfReaderExample
{
/// <summary>
/// 提取PDF指定页面的文本
/// <param name="filePath">PDF文件路径</param>
/// <param name="pageNumber">页码(从1开始)</param>
/// <returns>提取的文本内容</returns>
public string ExtractText(string filePath, int pageNumber)
{
// 使用using确保资源释放
using (PdfReader reader = new PdfReader(filePath))
{
// 调用PDF解析器提取文本
return PdfTextExtractor.GetTextFromPage(reader, pageNumber);
}
}
// 示例:提取第1页文本
public void ExampleUsage()
{
string text = ExtractText("example.pdf", 1);
Console.WriteLine("提取的文本:\n" + text);
}
}
关键点:
PdfReader会自动释放底层资源,避免内存泄漏。- 通过
GetTextFromPage方法,可灵活提取任意页码内容。
1.2 创建动态PDF文档
using iTextSharp.text;
using iTextSharp.text.pdf;
public class PdfWriterExample
{
/// <summary>
/// 生成包含表格的PDF
/// </summary>
public void GenerateInvoice(string outputPath)
{
// 创建文档对象并指定页面大小
Document document = new Document(PageSize.A4);
// 使用try-catch确保异常时资源释放
try
{
// 将文档绑定到输出流
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(outputPath, FileMode.Create));
// 打开文档
document.Open();
// 添加标题
document.Add(new Paragraph("发票", new Font(Font.FontFamily.HELVETICA, 18, Font.BOLD)));
// 创建表格(3列)
PdfPTable table = new PdfPTable(3);
table.WidthPercentage = 100; // 表格宽度占满页面
// 添加表头
table.AddCell("商品");
table.AddCell("数量");
table.AddCell("单价");
// 添加数据行
table.AddCell("笔记本");
table.AddCell("5");
table.AddCell("$10");
// 添加表格到文档
document.Add(table);
// 添加页脚
document.Add(new Paragraph("\n感谢惠顾!"));
}
catch (Exception ex)
{
Console.WriteLine("生成PDF失败:" + ex.Message);
}
finally
{
// 关闭文档(无论是否成功)
if (document.IsOpen())
{
document.Close();
}
}
}
}
关键点:
- 使用
PdfPTable创建复杂的表格结构。 - 通过
try-catch-finally确保资源正确释放。
第二章:PDFsharp——跨平台PDF操作利器
2.1 创建带图标的PDF
using PdfSharp.Drawing;
using PdfSharp.Pdf;
public class PdfSharpExample
{
/// <summary>
/// 生成包含图像和图形的PDF
/// </summary>
public void CreatePdfWithGraphics(string outputPath)
{
// 创建PDF文档
PdfDocument document = new PdfDocument();
document.Info.Title = "PDFsharp示例";
// 添加页面
PdfPage page = document.AddPage();
page.Width = XUnit.FromMillimeter(210); // A4宽度
page.Height = XUnit.FromMillimeter(297); // A4高度
// 获取绘图上下文
XGraphics gfx = XGraphics.FromPdfPage(page);
XFont font = new XFont("Arial", 20, XFontStyle.Bold);
// 绘制文本
gfx.DrawString("欢迎使用PDFsharp!", font, XBrushes.Black,
new XRect(0, 0, page.Width, page.Height), XStringFormats.Center);
// 绘制矩形
gfx.DrawRectangle(XPens.Blue, 50, 50, 100, 50);
// 插入图片(需确保图片路径存在)
using (XImage image = XImage.FromFile("logo.png"))
{
gfx.DrawImage(image, 100, 150, 100, 100);
}
// 保存文档
document.Save(outputPath);
}
}
关键点:
XGraphics类提供丰富的绘图API。- 支持直接插入图像文件(需处理异常)。
第三章:PdfiumViewer——无插件PDF预览解决方案
3.1 渲染PDF为图像并保存
using PdfiumViewer;
using System.Drawing.Imaging;
public class PdfRendererExample
{
/// <summary>
/// 将PDF页面渲染为PNG图像
/// </summary>
public void RenderToImage(string inputPath, string outputImagePath, int pageNumber)
{
// 加载PDF文档
using (var document = PdfDocument.Load(inputPath))
{
// 创建渲染器
var renderer = new PdfRenderer(document);
// 渲染指定页面
using (var stream = new FileStream(outputImagePath, FileMode.Create))
{
// 指定输出格式和分辨率
renderer.RenderToStream(pageNumber - 1, stream, ImageFormat.Png, 300); // 300dpi
}
}
}
}
关键点:
PdfRenderer类支持多种图像格式(PNG/JPG)。- 通过调整分辨率参数(如300dpi)平衡质量和性能。
第四章:PDFiumCore——高效处理大型PDF
4.1 提取PDF文本并分析
using PDFiumCore;
using System.Text;
public class PdfiumCoreExample
{
/// <summary>
/// 提取PDF全文本并统计关键词
/// </summary>
public void AnalyzePdf(string filePath)
{
// 初始化PDFium库
fpdfview.FPDF_InitLibrary();
// 加载文档
IntPtr document = fpdfview.FPDF_LoadDocument(filePath, null);
if (document == IntPtr.Zero)
{
Console.WriteLine("无法加载PDF文档。");
return;
}
// 获取总页数
int pageCount = fpdfview.FPDF_GetPageCount(document);
StringBuilder fullText = new StringBuilder();
// 遍历所有页面
for (int i = 0; i < pageCount; i++)
{
IntPtr page = fpdfview.FPDF_LoadPage(document, i);
if (page != IntPtr.Zero)
{
// 提取文本
IntPtr textHandle = fpdfview.FPDFText_GetText(page, 0, 0);
if (textHandle != IntPtr.Zero)
{
string text = Marshal.PtrToStringAnsi(textHandle);
fullText.AppendLine(text);
}
fpdfview.FPDF_ClosePage(page);
}
}
// 关闭文档并释放资源
fpdfview.FPDF_CloseDocument(document);
fpdfview.FPDF_DestroyLibrary();
// 分析关键词(示例:统计“合同”出现次数)
int contractCount = fullText.ToString().Split("合同").Length - 1;
Console.WriteLine($"关键词'合同'出现次数:{contractCount}");
}
}
关键点:
- 使用
FPDF_InitLibrary/FPDF_DestroyLibrary管理全局资源。 - 通过指针操作底层PDFium库,适合处理超大文件。
第五章:实战案例——发票管理系统
5.1 功能需求
- 自动生成发票PDF
- 合并多张发票为单个文件
- 提取发票关键字段(金额、日期)
5.2 代码实现:合并PDF文件
using iTextSharp.text.pdf;
public class InvoiceMerger
{
/// <summary>
/// 合并多个PDF文件
/// </summary>
public void MergeInvoices(string[] inputFiles, string outputFile)
{
using (PdfCopy copy = new PdfCopy(new Document(), new FileStream(outputFile, FileMode.Create)))
{
copy.Open();
foreach (string file in inputFiles)
{
using (PdfReader reader = new PdfReader(file))
{
for (int i = 1; i <= reader.NumberOfPages; i++)
{
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
}
copy.Close();
}
}
}
关键点:
- 使用
PdfCopy高效合并PDF。 - 通过循环遍历确保所有页面被正确导入。
第六章:避坑指南——常见问题解决方案
6.1 内存泄漏
现象:长时间运行后程序占用内存飙升。
解决方案:
- 使用
using语句确保PdfReader、Document等资源释放。 - 对于大文件,避免一次性加载全部内容。
6.2 权限异常
现象:UnauthorizedAccessException
解决方案:
- 检查文件路径是否有写入权限。
- 使用
FileAccess.ReadWrite模式打开文件流。
6.3 性能瓶颈
现象:处理大PDF时CPU占用过高。
解决方案:
- 使用异步操作(如
Task.Run)。 - 启用缓存机制减少重复计算。
选择最适合的PDF工具
| 库名称 | 优势 | 适用场景 |
|---|---|---|
| iTextSharp | 功能全面,社区活跃 | 企业级PDF处理 |
| PDFsharp | 跨平台,轻量级 | 移动端/嵌入式系统 |
| PdfiumViewer | 渲染质量高 | 预览/图像转换 |
| PDFiumCore | 高效处理超大文件 | 大数据PDF分析 |
到此这篇关于.NET操作PDF的完整指南的文章就介绍到这了,更多相关.NET操作PDF内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
