如何使用iText7 C#导入仅含注释(无表单域)的FDF/XFDF至PDF
问题描述
尝试使用iText7 C#将仅包含注释(无AcroForm表单域)的FDF/XFDF文档导入PDF,现有FDF和XFDF内容如下,自行编写的代码未能成功添加注释,求解决方案。
FDF文档内容
%FDF-1.2 %âãÏÓ 1 0 obj << /FDF << /Annots[2 0 R]/F(/C/Users/Desktop/Emptypdf.pdf)/ID[<> <>]/UF(/C/Users/Desktop/Emptypdf.pdf)>> /Type/Catalog >> endobj 2 0 obj << /Author(SYSTEM)/C[0.0 0.72 0.92]/Contents(FA)/DA(0 G 0 0.72 0.92 rg 0 Tc 0 Tw 100 Tz 0 TL 0 Ts 0 Tr /Arial 12 Tf)/DS(font: Arial,sans-serif 12.0pt; text-align:left; color:#00B8EB )/F 4/M(D:20230829121640+05'30')/NM(FA in page 1)/Page 0/RC(<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:23.3.0" xfa:spec="2.0.2" ><p dir="ltr"><span dir="ltr" style="font-size:12.0pt;text-align:left;color:#FF0000;font-weight:normal;font-style:normal">FA</span></p></body>)/Rect[10.0 565.44 55.7559 585.44]/Subj(Text Box)/Subtype/FreeText/Type/Annot >> endobj trailer << /Root 1 0 R >> %%EOF
XFDF文档内容
<?xml version="1.0" encoding="UTF-8"?> <xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve" ><annots ><freetext color="#00B8EB" flags="print" date="D:20230829121640+05'30'" name="FA in page 1" page="0" rect="10.000000,565.440000,55.755900,585.440000" subject="Text Box" ><contents-richtext ><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:23.3.0" xfa:spec="2.0.2" ><p dir="ltr" ><span dir="ltr" style="font-size:12.0pt;text-align:left;color:#FF0000;font-weight:normal;font-style:normal" >FA</span ></p ></body ></contents-richtext ><defaultappearance >0 G 0 0.72 0.92 rg 0 Tc 0 Tw 100 Tz 0 TL 0 Ts 0 Tr /Arial 12 Tf</defaultappearance ><defaultstyle >font: Arial,sans-serif 12.0pt; text-align:left; color:#00B8EB </defaultstyle ></freetext ></annots ><f href="Emptypdf_acrf.pdf" /><ids original="F7F892FBFFEABF49A24F61F6C466DB21" modified="F7F892FBFFEABF49A24F61F6C466DB21" /></xfdf >
尝试的无效代码
// Replace with the paths to your PDF and FDF files string pdfFilePath = "C:\\blankpage.pdf"; string fdfFilePath = "C:\\blankpage.xfdf"; using (PdfReader pdfReader = new PdfReader(pdfFilePath)) { using (FileStream fs = new FileStream(fdfFilePath, FileMode.Open, FileAccess.Read)) { XmlDocument fdfDoc = new XmlDocument(); fdfDoc.Load(fs); var nsmgr = new XmlNamespaceManager(fdfDoc.NameTable); nsmgr.AddNamespace("a", "http://ns.adobe.com/xfdf/"); XmlNodeList commentNodes = fdfDoc.SelectNodes("//a:annots", nsmgr); foreach (XmlNode commentNode in commentNodes) { string annotationText = commentNode.InnerText; // Apply the annotationText to the PDF using iTextSharp PdfDictionary pageDict = pdfReader.GetPageN(1); // Change 1 to the page number you need PdfArray annotsArray = pageDict.GetAsArray(PdfName.ANNOTS); if (annotsArray == null) { annotsArray = new PdfArray(); pageDict.Put(PdfName.ANNOTS, annotsArray); } PdfDictionary commentDict = new PdfDictionary(); commentDict.Put(PdfName.TYPE, new PdfName("Annot")); commentDict.Put(PdfName.SUBTYPE, new PdfName("Text")); commentDict.Put(PdfName.CONTENTS, new PdfString(annotationText, PdfObject.TEXT_UNICODE)); // Set other annotation properties here annotsArray.Add(commentDict); } using (FileStream outputPdfStream = new FileStream("C:\\output.pdf", FileMode.Create)) { using (PdfStamper stamper = new PdfStamper(pdfReader, outputPdfStream)) { stamper.Close(); } } } }
解决方案
你的代码存在几个核心问题:
- 混用了iTextSharp(
PdfStamper属于旧版本iTextSharp)和iText7的API,两者不兼容 - 手动解析XFDF时仅提取了文本内容,遗漏了注释的位置、样式、类型等关键属性
- 注释类型设置错误(你设置的是
Text注释,但实际是FreeText注释)
使用iText7的内置工具可以直接完成FDF/XFDF注释的导入,无需手动解析XML,以下是正确的代码片段:
导入XFDF注释的代码
using iText.Kernel.Pdf; using iText.Kernel.Pdf.Annot; using iText.Forms.Xfdf; string pdfPath = "C:\\blankpage.pdf"; string xfdfPath = "C:\\blankpage.xfdf"; string outputPath = "C:\\output.pdf"; // 读取原始PDF using (PdfReader reader = new PdfReader(pdfPath)) using (PdfWriter writer = new PdfWriter(outputPath)) using (PdfDocument pdfDoc = new PdfDocument(reader, writer)) { // 加载XFDF文档 XfdfReader xfdfReader = new XfdfReader(xfdfPath); // 遍历XFDF中的所有注释 foreach (XfdfAnnotation xfdfAnnot in xfdfReader.GetAnnotations()) { // 将XFDF注释转换为iText7的PdfAnnotation对象 PdfAnnotation pdfAnnot = xfdfAnnot.MakeAnnotation(pdfDoc); // 获取注释对应的页面(XFDF中page从0开始,iText7中从1开始) PdfPage page = pdfDoc.GetPage(xfdfAnnot.GetPageIndex() + 1); // 将注释添加到页面 page.AddAnnotation(pdfAnnot); } }
导入FDF注释的代码
如果使用的是FDF文件而非XFDF,代码类似,只需替换为FdfReader:
using iText.Kernel.Pdf; using iText.Kernel.Pdf.Annot; using iText.Forms.Fdf; string pdfPath = "C:\\blankpage.pdf"; string fdfPath = "C:\\blankpage.fdf"; string outputPath = "C:\\output.pdf"; using (PdfReader reader = new PdfReader(pdfPath)) using (PdfWriter writer = new PdfWriter(outputPath)) using (PdfDocument pdfDoc = new PdfDocument(reader, writer)) { using (FdfReader fdfReader = new FdfReader(fdfPath)) { PdfDictionary fdfDict = fdfReader.GetFdfObject(); PdfArray annotsArray = fdfDict.GetAsArray(PdfName.Annots); if (annotsArray != null) { foreach (var annotObj in annotsArray) { PdfDictionary annotDict = ((PdfIndirectReference)annotObj).GetRefersTo() as PdfDictionary; if (annotDict != null) { // 获取页面索引(FDF中Page从0开始) int pageIndex = annotDict.GetAsNumber(PdfName.Page).IntValue() + 1; PdfPage page = pdfDoc.GetPage(pageIndex); // 创建PdfAnnotation并添加到页面 PdfAnnotation pdfAnnot = PdfAnnotation.MakeAnnotation(annotDict); page.AddAnnotation(pdfAnnot); } } } } }
关键说明
- 确保引用正确的iText7 NuGet包:
iText7.Core和iText7.Forms(处理FDF/XFDF需要Forms包) - 代码自动处理注释的所有属性(位置、颜色、字体、样式等),无需手动设置
- 注意页面索引的转换:FDF/XFDF中页面从0开始计数,iText7的
PdfDocument.GetPage()从1开始
内容的提问来源于stack exchange,提问作者Kothandaraman
相关产品推荐
相关产品推荐

