合并多PDF至单页生成样册时遇System.ObjectDisposedException问题求助
解决iTextSharp合并PDF时的System.ObjectDisposedException错误
问题描述
尝试将多个PDF文件合并为单个PDF文档生成样册,使用基于iTextSharp的C#代码运行时抛出错误:
System.ObjectDisposedException: Cannot access a closed file.
原代码如下:
using System; using System.IO; using iTextSharp.text; using iTextSharp.text.pdf; namespace CutAndPaste { class Program { public static readonly string SRC = Environment.CurrentDirectory + "\\pdfs\\2.pdf"; public static readonly string SRC2 = Environment.CurrentDirectory + "\\pdfs\\3.pdf"; public static readonly string DEST = Environment.CurrentDirectory + "\\output.pdf"; static void Main(string[] args) { MergePDFs(DEST, SRC, SRC2); Console.WriteLine("PDF'ler başarıyla birleştirildi."); } static void MergePDFs(string destPath, params string[] sourcePaths) { using (FileStream fs = new FileStream(destPath, FileMode.Create, FileAccess.Write, FileShare.None)) using (Document doc = new Document()) using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) { doc.Open(); PdfContentByte cb = writer.DirectContent; foreach (string sourcePath in sourcePaths) { using (PdfReader reader = new PdfReader(sourcePath)) { for (int pageNumber = 1; pageNumber <= reader.NumberOfPages; pageNumber++) { doc.NewPage(); PdfImportedPage page = writer.GetImportedPage(reader, pageNumber); cb.AddTemplate(page, 0, 0); } } } } } } }
问题分析
原实现方式存在两个核心问题:
- 错误的合并方式:使用
PdfWriter+AddTemplate并非iTextSharp合并PDF的标准方案,该方式是将原页面作为模板绘制到新页面,资源管理逻辑复杂。 - 资源释放顺序错误:循环内的
PdfReader被using块包裹,处理完当前PDF页面后立即释放,但PdfWriter的写入操作是缓冲式的,后续写入时仍会依赖已释放的PdfReader资源,从而触发ObjectDisposedException。
修复方案
使用iTextSharp专门用于PDF合并的PdfCopy类,该类会自动处理资源管理和页面复制逻辑,避免上述问题。修复后的代码如下:
using System; using System.IO; using iTextSharp.text; using iTextSharp.text.pdf; namespace CutAndPaste { class Program { // 使用Path.Combine替代字符串拼接,提升路径安全性与跨平台兼容性 public static readonly string SRC = Path.Combine(Environment.CurrentDirectory, "pdfs", "2.pdf"); public static readonly string SRC2 = Path.Combine(Environment.CurrentDirectory, "pdfs", "3.pdf"); public static readonly string DEST = Path.Combine(Environment.CurrentDirectory, "output.pdf"); static void Main(string[] args) { MergePDFs(DEST, SRC, SRC2); Console.WriteLine("PDF'ler başarıyla birleştirildi."); } static void MergePDFs(string destPath, params string[] sourcePaths) { using (FileStream fs = new FileStream(destPath, FileMode.Create, FileAccess.Write, FileShare.None)) using (Document doc = new Document()) // 用PdfCopy替换PdfWriter,专门处理PDF合并场景 using (PdfCopy copy = new PdfCopy(doc, fs)) { doc.Open(); foreach (string sourcePath in sourcePaths) { using (PdfReader reader = new PdfReader(sourcePath)) { for (int pageNumber = 1; pageNumber <= reader.NumberOfPages; pageNumber++) { // 获取原页面尺寸,确保目标页面与原页面尺寸一致 Rectangle pageSize = reader.GetPageSize(pageNumber); doc.SetPageSize(pageSize); doc.NewPage(); // 复制原页面到目标PDF copy.AddPage(copy.GetImportedPage(reader, pageNumber)); } } } } } } }
关键改动说明
- 替换合并工具类:
PdfCopy是iTextSharp为PDF合并场景设计的类,内部已优化资源管理逻辑,避免缓冲写入时的资源访问问题。 - 页面尺寸适配:读取原页面的尺寸并设置为目标文档的当前页面尺寸,避免出现页面布局错乱。
- 路径优化:使用
Path.Combine替代硬编码的字符串拼接,提升代码的可维护性与跨平台兼容性。
内容的提问来源于stack exchange,提问作者Zafer AKKÖSE
相关产品推荐
相关产品推荐

