iTextSharp合并PDF页面错乱因未按文件顺序逐页读取,应显式排序路径并循环调用AddPage;中文乱码需用PdfCopyFields或手动注册字体;大文件OOM建议升级iText7或改用PdfSmartCopy;书签丢失须弃用PdfCopy改用PdfCopyFields或iText7的PdfMerger。

用 iTextSharp 合并 PDF 时页面顺序错乱
合并后页面顺序和输入文件列表不一致,本质是没按 FileStream 打开顺序逐页读取。iTextSharp 的 PdfCopy 不自动维护文档间页序,它只按你调用 addPage() 的时机塞入页面。
实操建议:
- 用
List<string></string>明确声明文件路径顺序,别依赖Directory.GetFiles()的返回顺序(它受文件系统影响) - 对每个
PdfReader,用reader.NumberOfPages循环调用copy.AddPage(copy.GetImportedPage(reader, i)),i 从 1 开始(PDF 页码从 1 计) - 别在循环外提前关闭
PdfReader——PdfCopy需要 reader 实例存活到copy.Close()前
合并后中文乱码或字体丢失
原始 PDF 若嵌入了自定义字体(比如宋体、思源黑体),而目标文档没做字体映射,iTextSharp 默认用 Helvetica 替代,结果就是方块或空白。
实操建议:
- 用
PdfCopyFields替代PdfCopy,它保留源文档的字体、书签、表单域等结构信息 - 若必须用
PdfCopy,需手动注册字体:BaseFont.CreateFont("C:\Windows\Fonts\simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED),再通过PdfContentByte注入文字(仅适用于添加新内容,不修复已有乱码) - 检查源 PDF 是否真嵌入字体:用 Adobe Acrobat → 文件 → 属性 → 字体标签页,标“Embedded Subset”才安全
大文件合并报 OutOfMemoryException
iTextSharp 5.x 默认把整个 PDF 解析进内存,合并 10 个 50MB 的文件很容易触发 OutOfMemoryException,尤其在 32 位进程或内存受限环境。
实操建议:
- 升级到 iTextSharp 7(
iText7.kernel),它支持流式处理,用PdfMerger+PdfDocument(带new PdfWriter(outputStream, new WriterProperties().SetLinearization(true)))可显著降内存 - 若只能用 v5,改用
PdfSmartCopy:它复用相同资源(如图片、字体),比PdfCopy内存占用低 30%~50% - 避免一次性读取所有文件到
byte[];改用FileStream流式传入PdfReader
合并后书签/目录丢失
PdfCopy 完全忽略源 PDF 的 Outline(即书签树),这是设计使然——它定位是“页面拼接”,不是“文档整合”。
实操建议:
- 必须保留书签,就别用
PdfCopy;改用PdfCopyFields,它会自动合并reader.Outlines - 若用 iText7,
PdfMerger支持mergeOutlines = true参数,但要注意:同级书签名重复时会覆盖,需提前重命名 - 手动生成书签?可以,但得遍历每个
PdfReader的Outlines,再用PdfOutline逐级重建——这活儿容易漏层级或错偏移量,不推荐除非有定制需求
真正麻烦的不是“怎么拼”,是拼完要不要保持原样:书签、字体、超链接、表单字段、甚至 PDF/A 合规性。选错类(PdfCopy vs PdfCopyFields vs PdfMerger)之后,补救成本远高于一开始选对。










