我有一个pdf文件,其中包含一些我想从java填写的表单字段。现在我正在尝试填写一个我通过其名称找到的表单。我的代码如下所示:
File file = new File("c:/Testy/luxmed/Skierowanie3.pdf");
PDDocument document = PDDocument.load(file);
PDDocumentCatalog doc = document.getDocumentCatalog();
PDAcroForm Form = doc.getAcroForm();
String formName = "topmostSubform[0].Page1[0].pana_pania[0]";
PDField f = Form.getField(formName);
setField(document, formName, "Artur");
System.out.println("New value 2nd: " + f.getValueAsString());
document.saveIncremental(new FileOutputStream("c:/Testy/luxmed/nowy_pd3.pdf"));
document.close();
这是:
public static void setField(PDDocument pdfDocument, String name, String Value) throws IOException
{
PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
PDAcroForm acroForm = docCatalog.getAcroForm();
PDField field = acroForm.getField(name);
if (field instanceof PDCheckBox){
field.setValue("Yes");
}
else if (field instanceof PDTextField){
System.out.println("Original value: " + field.getValueAsString());
field.setValue(Value);
System.out.println("New value: " + field.getValueAsString());
}
else{
System.out.println("Nie znaleziono pola");
}
}
作为系统。out状态下,该值设置正确,但在生成的pdf文件中,新值未显示(显示原始字符串),因此我猜增量保存无法正常工作。我错过了什么?
我使用2.0.2版本的pdfbox,下面是我使用的pdf文件:pdf
使用PDFBox 2.0将更改保存为PDF增量更新时。x、 对于每个更改的PDF对象,必须将属性NeedToBeUpdated
设置为true
。此外,该对象必须可以通过引用链从PDF目录中访问,并且该链中的每个PDF对象还必须将属性needtoUpdated
设置为true
。
这是由于PDFBox以增量方式保存的方式,从它检查NeedToBeUpated
属性的曲库开始,如果它设置为true
,PDFBox将存储该对象,并且只有在这种情况下,它才会更深入地递归到从此对象引用的对象中,以搜索要存储的更多对象。
特别是,这意味着某些对象不必要地必须标记NeedToBeUpdate
,例如PDF曲库本身,在某些情况下,这甚至破坏了增量更新的目的,见下文。
一方面,必须扩展setField
方法来标记字段字典链,直到并包括更改的字段以及外观:
public static void setField(PDDocument pdfDocument, String name, String Value) throws IOException
{
PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
PDAcroForm acroForm = docCatalog.getAcroForm();
PDField field = acroForm.getField(name);
if (field instanceof PDCheckBox) {
field.setValue("Yes");
}
else if (field instanceof PDTextField) {
System.out.println("Original value: " + field.getValueAsString());
field.setValue(Value);
System.out.println("New value: " + field.getValueAsString());
}
else {
System.out.println("Nie znaleziono pola");
}
// vvv--- new
COSDictionary fieldDictionary = field.getCOSObject();
COSDictionary dictionary = (COSDictionary) fieldDictionary.getDictionaryObject(COSName.AP);
dictionary.setNeedToBeUpdated(true);
COSStream stream = (COSStream) dictionary.getDictionaryObject(COSName.N);
stream.setNeedToBeUpdated(true);
while (fieldDictionary != null)
{
fieldDictionary.setNeedToBeUpdated(true);
fieldDictionary = (COSDictionary) fieldDictionary.getDictionaryObject(COSName.PARENT);
}
// ^^^--- new
}
(FillInFormSaveIncremental方法设置字段
)
另一方面,必须扩展主html" target="_blank">代码,以标记从目录到字段数组的链:
PDDocument document = PDDocument.load(...);
PDDocumentCatalog doc = document.getDocumentCatalog();
PDAcroForm Form = doc.getAcroForm();
String formName = "topmostSubform[0].Page1[0].pana_pania[0]";
PDField f = Form.getField(formName);
setField(document, formName, "Artur");
System.out.println("New value 2nd: " + f.getValueAsString());
// vvv--- new
COSDictionary dictionary = document.getDocumentCatalog().getCOSObject();
dictionary.setNeedToBeUpdated(true);
dictionary = (COSDictionary) dictionary.getDictionaryObject(COSName.ACRO_FORM);
dictionary.setNeedToBeUpdated(true);
COSArray array = (COSArray) dictionary.getDictionaryObject(COSName.FIELDS);
array.setNeedToBeUpdated(true);
// ^^^--- new
document.saveIncremental(new FileOutputStream(...));
document.close();
(FillInFormSaveIncremental testtestFillInSkierowanie3
)
注意:对于通用PDF,显然应该引入一些null
测试。。。
在Adobe Reader中打开结果文件会不幸地看到程序抱怨禁用文件中扩展功能的更改。
这是由于PDFBox增量保存中的一个怪癖,即在更新部分需要一些不必要的对象。尤其是目录保存在那里,其中包含使用权签名(授予扩展功能的技术)。重新保存的签名显然不再位于原始版本中的原始位置。因此,它是无效的。
OP很可能希望以增量方式保存PDF,以避免破坏此签名,但PDFBox不允许这样做。哦,好吧。。。
因此,唯一能做的就是通过完全删除签名来防止警告。
我们已经在上面的添加中检索到了catalog对象,因此删除签名很容易:
COSDictionary dictionary = document.getDocumentCatalog().getCOSObject();
// vvv--- new
dictionary.removeItem(COSName.PERMS);
// ^^^--- new
dictionary.setNeedToBeUpdated(true);
(FillInFormSaveIncremental testtestFillInSkierowanie3
)
不幸的是,在Adobe Reader one中打开结果文件时,程序会抱怨文件中缺少用于保存的扩展功能。
这是因为Adobe Reader需要扩展功能来保存对XFA表单的更改,我们必须在此步骤中删除扩展功能。
但手头的文档是混合AcroForm
我们已经在上面的添加中检索到acroform对象,因此从中删除引用的XFA表单很容易:
dictionary = (COSDictionary) dictionary.getDictionaryObject(COSName.ACRO_FORM);
// vvv--- new
dictionary.removeItem(COSName.XFA);
// ^^^--- new
dictionary.setNeedToBeUpdated(true);
(FillInFormSaveIncremental testtestFillInSkierowanie3
)
在AdobeReader中打开结果文件,您将看到现在可以无需进一步的ado即可编辑表单并保存文件。
注意,这需要一个足够新的Adobe Reader版本,早期版本(至少达到版本9)确实需要扩展功能,即使是保存对AcroForm表单的更改
当我使用这个长字段名时,我没有得到任何错误,但是得到的PDF不包含我放在字段中的值。我想可能字段名有问题,所以我使用了Pdftk工具,它只给出了作为字段名。但是当我仅仅使用它时,我会得到error。救命?
我的PDFBox有问题。我有一个PDF格式的空白页,我想在其中插入图像。因为我也使用签名PDF,所以所有更改都必须保存为“saveIncremental”。 当我只插入一个图像时,一切都很好(图像已被插入)。当我试图在这个PDF中插入另一个图像时,它没有被插入,当在Adobe Acrobat Reader中打开时,它说“此页面存在错误。Adobe可能无法正确显示页面...”。 奇怪的事情-当PDF
在Thymeleaf中,我可以使用 但是我不知道如何输出到表单动作属性中。 有人对Thymeleaf超文本标记语言有什么想法吗? 样例JavaSpring-MVC控制器代码
问题内容: 我无法手动或自动在新保存的对象上填充创建者字段……我能找到的唯一方法是重新查询我已经想要做的对象。 这是设置: 这是我拉头发的地方 编辑:最新的猫鼬解决了此问题并添加了填充功能,请参见新的接受的答案。 问题答案: 您应该能够使用模型的填充函数来执行此操作:http : //mongoosejs.com/docs/api.html#model_Model.populate 在书籍的保存处
您是否设法在横向模式下填充PDF文档? 谢谢你的帮助。
我在用ApachePDFBox填写PDF表格。我使用的是TrueType字体(不是默认字体),叫做“Impact”,非常标准。在模板中,我有一个名为“Title”的字段,指定了影响字体。我使用下面的代码获取该模板,并用一个包含多个单词的值填充该字段。 问题是,当你查看创建的PDF时,单词之间有很大的空格。如果在Acrobat中打开PDF并单击该字段,文本将发生变化,大间距将消失。以任何方式编辑该字