新项目不建议用itextsharp因其已停更且agpl许可证具传染性;应改用itext 7 for .net,注意中文需注册cjk字体、pdf叠加须用pdfcanvas、合并pdf需pdfmerger开启深层复制。

为什么新项目不建议用 iTextSharp
iTextSharp 是 iText 5 的 .NET 移植版,官方早在 2016 年就停止维护,且其许可证(AGPL)在商业项目中极易触发传染性条款——只要部署了含 iTextSharp 的应用,就必须开源整个项目。很多团队踩过这个坑:上线后法务突然叫停,临时换库重写 PDF 生成功能。现在稳定、合规、活跃的替代是 iText 7 for .NET(iText7),它采用更宽松的 AGPL + 商业双许可,NuGet 包名是 itext7 而非 iTextSharp。
用 iText 7 生成带中文的 PDF(字体是关键)
直接用 Document.Add(new Paragraph("你好")) 会输出方块或空格——iText 7 默认不支持 GBK/UTF-8 中文。必须显式注册并使用支持 CJK 的字体:
var font = PdfFontFactory.CreateFont(@"C:\Windows\Fonts\simhei.ttf",
PdfEncodings.IDENTITY_H, true); // 注意第三个参数必须为 true
var paragraph = new Paragraph("你好,世界").SetFont(font).SetFontSize(12);
document.Add(paragraph);
-
PdfEncodings.IDENTITY_H是处理中文必需的编码,不能用BaseFont.IDENTITY_H(那是 iText 5 的写法) - 字体路径推荐用
SystemFonts.GetFontList()列出可用系统字体,避免硬编码路径 - 若部署到 Linux 服务器,不能依赖
simhei.ttf,应改用 NotoSansCJK 或将字体文件随程序发布
向现有 PDF 插入文字或图片(不是“编辑”,而是覆盖)
iText 7 不支持真正意义上的“编辑”PDF(如删段落、改字号),只能通过 PdfCanvas 在指定页上层叠加内容。常见错误是直接调用 document.Add()——这会追加新页,而非修改原页:
using var reader = new PdfReader("input.pdf");
using var writer = new PdfWriter("output.pdf");
using var pdfDoc = new PdfDocument(reader, writer);
var page = pdfDoc.GetPage(1);
var canvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
canvas.BeginText()
.SetFontAndSize(font, 14)
.MoveText(50, 750)
.ShowText("已签收")
.EndText();
-
NewContentStreamBefore()表示文字画在原内容下方;用NewContentStreamAfter()才能盖在上方 - 坐标原点在左下角,Y 值从 0 开始向上增长,别套用 Windows 窗体坐标习惯
- 插入图片需先用
ImageDataFactory.Create("logo.png")加载,再用canvas.AddImageAt()
合并多个 PDF 时如何保留书签和表单字段
简单循环 CopyPagesTo() 会丢掉源 PDF 的交互元素。要保留结构,必须用 PdfMerger 并开启深层复制:
var merger = new PdfMerger(destPdfDoc);
foreach (var srcPath in sourcePaths) {
using var srcDoc = new PdfDocument(new PdfReader(srcPath));
// 关键:true 表示复制书签、AcroForm、OCGs 等元数据
merger.Merge(srcDoc, true);
}
- 若源 PDF 含签名或加密,
PdfReader构造时需传入密码,否则抛BadPasswordException - 合并后若想统一设置页面大小,不能对
destPdfDoc直接调GetPage(i).SetPageSize(),而应在Merge()前对每个srcDoc单独处理 - 表单字段(AcroForm)合并后默认可编辑;如需设为只读,得遍历
destPdfDoc.GetAcroForm().GetFormFields().Values手动调SetReadOnly(true)










