我有一个包含已填写字段的 PDF 表单。如果我尝试阅读 acrofield,它们是空的。但在 PDF 中我可以更改值并保存它们。
namespace Tutorial {
public class FillForm {
public const String SRC = "../../../resources/pdf/dnd-character.pdf";
public const String DEST = "../../../results/fill_dnd.pdf";
public static void Main(String[] args) {
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new FillForm().ManipulatePdf(SRC, DEST);
}
public virtual void ManipulatePdf(String src, String dest) {
PdfDocument pdf = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
PdfAcroForm form = PdfFormCreator.GetAcroForm(pdf, true);
IDictionary<String, PdfFormField> fields = form.GetAllFormFields();
Console.WriteLine(fields.Count);
foreach(KeyValuePair<string, PdfFormField> entry in fields)
{
Console.WriteLine(entry.Key);
}
pdf.Close();
}
}
}
这是 pdf:PDF
我的代码适用于其他 PDF,因此我确信这是一个 PDF 问题。这是一个可以使用的 PDF:PDF2
我尝试自己研究这个问题,但我能找到的最好的就是这里过时的堆栈问题:ItextSharp - Acrofields 是空的
此解决方案使用以下行:
PdfArray fields = form.GetAsArray(PdfName.Fields);
返回错误:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
然后我看了这个问题:iText Acrofields Are Empty, form.getAsArray(PdfName.FIELDS) is is null
同样,这个解决方案使用
form.GetAsArray(PdfName.Fields);
所以这个解决方案对我来说也失败了。我还检查了问题中的 Xfa,但似乎没有出现
XfaForm xfa = form.GetXfaForm();
xfa.IsXfaPresent() // returns false
但是,这个问题让我查看了 RUPS 中的 PDF 层次结构,我注意到了一个差异。以下是有效 PDF 的层次结构:
突出显示的 /T 是我想用来获取 /V 内的字符串的引用
这是不起作用的 pdf 层次结构:
再次,想要 /V 使用 /T (或任何其他方式来专门获得 /V 真正)。那么,我该如何处理这个看似糟糕的 pdf 来获取我想要的信息呢?
正如您自己在问题本身中指出的那样,这里的问题来自这样一个事实:这个“损坏的”PDF 文件包含小部件注释,但在目录中不包含
AcroForm
条目。该条目基本上充当与表单字段和小部件相关的所有内容的入口点,并且由于缺少该条目,iText 无法以通常的方式检索所需的信息。
但是仍然可以获得这些信息。为此,需要遍历文档中的所有页面并收集所有小部件。 像这样的事情应该可以解决问题:
using (PdfDocument pdfDocument1 = new PdfDocument(new PdfReader("DnD-Character.pdf")))
{
for (int i = 1; i < pdfDocument1.GetNumberOfPages() + 1; ++i)
{
PdfPage page = pdfDocument1.GetPage(i);
foreach (PdfAnnotation annotation in page.GetAnnotations())
{
if (PdfName.Widget.Equals(annotation.GetSubtype()))
{
Console.WriteLine("Name: " + annotation.GetPdfObject().Get(PdfName.T));
Console.WriteLine("Value: " + annotation.GetPdfObject().Get(PdfName.V));
}
}
}
}