保存的文本字段值没有正确使用PDF PDFBOX

问题描述:

import java.io.IOException; 

import javax.swing.text.BadLocationException; 

import org.apache.pdfbox.cos.COSArray; 
import org.apache.pdfbox.cos.COSDictionary; 
import org.apache.pdfbox.cos.COSFloat; 
import org.apache.pdfbox.cos.COSName; 
import org.apache.pdfbox.cos.COSString; 
import org.apache.pdfbox.exceptions.COSVisitorException; 
import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.pdmodel.PDPage; 
import org.apache.pdfbox.pdmodel.interactive.action.PDAnnotationAdditionalActions; 
import org.apache.pdfbox.pdmodel.interactive.action.type.PDActionJavaScript; 
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; 
import org.apache.pdfbox.pdmodel.interactive.form.PDTextbox; 
import org.junit.Test; 

public class TestPDTextbox { 
    @Test 
    public void Sample1() throws IOException, COSVisitorException, BadLocationException { 


     PDDocument doc = new PDDocument(); 
     PDPage page = new PDPage(); 
     doc.addPage(page); 

     COSDictionary acroFormDict = new COSDictionary(); 
//  acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true); 
     acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray()); 

     PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict); 
     doc.getDocumentCatalog().setAcroForm(acroForm); 

     COSDictionary cosDict1 = new COSDictionary(); 
     COSArray rect1 = new COSArray(); 
     rect1.add(new COSFloat(100)); 
     rect1.add(new COSFloat(700)); 
     rect1.add(new COSFloat(200)); 
     rect1.add(new COSFloat(750)); 

     cosDict1.setItem(COSName.RECT, rect1); 
     cosDict1.setItem(COSName.FT, COSName.getPDFName("Tx")); // Field Type 
     cosDict1.setItem(COSName.TYPE, COSName.ANNOT); 
     cosDict1.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget")); 
     cosDict1.setItem(COSName.T, new COSString("tx1")); 
     cosDict1.setItem(COSName.DA, new COSString("/Helv 7 Tf 0 g")); 
     cosDict1.setItem(COSName.V, new COSString("Test Value1")); 

     PDTextbox textbox = new PDTextbox(doc.getDocumentCatalog().getAcroForm(), cosDict1); 

//  textbox.setValue("Test Value"); 

     page.getAnnotations().add(textbox.getWidget()); 
     acroForm.getFields().add(textbox); 

     doc.save("C:\\PDF\\SampleTextbox.pdf"); 
     doc.close(); 
    } 
} 

问题#1 我已经创建一个文本字段如上面的代码,并试图设定值使用textbox.setValue(“测试显示生成的值”);的方法,但如下所示,它给错误:保存的文本字段值没有正确使用PDF PDFBOX

java.io.IOException: Error: Don't know how to calculate the position for non-simple fonts 
    at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.getTextPosition(PDAppearance.java:1037) 
    at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.insertGeneratedAppearance(PDAppearance.java:558) 
    at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.setAppearanceValue(PDAppearance.java:338) 
    at org.apache.pdfbox.pdmodel.interactive.form.PDVariableText.setValue(PDVariableText.java:131) 
    at sample.pdfbox.example.TestPDTextbox.Sample1(TestPDTextbox.java:54) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 

问题#2

为了解决问题#1,如果我使用cosDictionary属性 即cosDict1.setItem设置TextBox的值(COSName.V,新的COSString(“Test Value1”));

然后在Adobe Reader中,textBox的值未正确填充。 我必须点击文本框,然后才会出现值,并且一旦我从该字段中移出,值再次变为不可见。

问题3:

为了解决问题#2,我需要needAppearances标志设置为true,如下图所示,并以PDF正确显示的字段值之后。但是在此解决方案之后,一旦用户更改了字段值,我们就无法提取/解析P​​DF字段,并且我们再次解析此PDF。

注: -这个问题在Adobe Reader中存在,在此同时打开PDF它提供了一些消息太像固定表单字段了。一旦我保存PDF并尝试解析acroform字段,所有字段都将被重置或为空。无法提取字段名称或字段值。

所以使用acroFormDict.setBoolean(COSName.getPDFName(“NeedAppearances”),true);在代码中似乎有风险,并且它在PDF解析中创建了其他问题,因此无法使用它。

COSDictionary acroFormDict = new COSDictionary(); 
     acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true); 
     acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray()); 

     PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict); 
     doc.getDocumentCatalog().setAcroForm(acroForm); 

我想,我需要设置PDAppearanceDictionary文本字段,但我不`吨知道要做到这一点,我是否需要为每个字段或在acroform级别设置。

请帮我解决这个问题,我该如何解决。 我使用PDFBOX版本1.8.10。

+0

我能打开与AR文件,编辑字段,保存文件,然后重新打开这样的:DOC = PDDocument.load(“SampleTextbox2 .PDF“); PDField field = doc.getDocumentCatalog()。getAcroForm()。getField(“tx1”); System.out.println(field.getValue()); doc.close(); 并且输出是测试值2,即修改值。 –

在上面的问题中,我通过向acroform添加页面资源并使用正确的默认外观字符串来修复问题#1。现在我不需要将需求标志设置为true。

 PDFont font = PDType1Font.HELVETICA; 
     PDResources res = new PDResources(); 
     String fontName = res.addFont(font); 
     String defaultAppearance = "/"+fontName+" 7 Tf 0 g"; 

     COSDictionary acroFormDict = new COSDictionary(); 
     acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), false); 
     acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray()); 
     acroFormDict.setItem(COSName.DA, new COSString(defaultAppearance)); 

     PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict); 
     acroForm.setDefaultResources(res); 

检查整个更正如下代码:

import java.io.IOException; 

import javax.swing.text.BadLocationException; 

import org.apache.pdfbox.cos.COSArray; 
import org.apache.pdfbox.cos.COSDictionary; 
import org.apache.pdfbox.cos.COSFloat; 
import org.apache.pdfbox.cos.COSName; 
import org.apache.pdfbox.cos.COSString; 
import org.apache.pdfbox.exceptions.COSVisitorException; 
import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.pdmodel.PDPage; 
import org.apache.pdfbox.pdmodel.PDResources; 
import org.apache.pdfbox.pdmodel.font.PDFont; 
import org.apache.pdfbox.pdmodel.font.PDType1Font; 
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; 
import org.apache.pdfbox.pdmodel.interactive.form.PDTextbox; 
import org.junit.Test; 

public class TestPDTextbox { 
    @Test 
    public void Sample1() throws IOException, COSVisitorException, BadLocationException { 


     PDDocument doc = new PDDocument(); 
     PDPage page = new PDPage(); 
     doc.addPage(page); 

     PDFont font = PDType1Font.HELVETICA; 
     PDResources res = new PDResources(); 
     String fontName = res.addFont(font); 
     String defaultAppearance = "/"+fontName+" 7 Tf 0 g"; 

     COSDictionary acroFormDict = new COSDictionary(); 
     acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), false); 
     acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray()); 
     acroFormDict.setItem(COSName.DA, new COSString(defaultAppearance)); 

     PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict); 
     acroForm.setDefaultResources(res); 

     doc.getDocumentCatalog().setAcroForm(acroForm); 

     COSDictionary cosDict1 = new COSDictionary(); 
     COSArray rect1 = new COSArray(); 
     rect1.add(new COSFloat(100)); 
     rect1.add(new COSFloat(700)); 
     rect1.add(new COSFloat(200)); 
     rect1.add(new COSFloat(750)); 

     cosDict1.setItem(COSName.RECT, rect1); 
     cosDict1.setItem(COSName.FT, COSName.getPDFName("Tx")); // Field Type 
     cosDict1.setItem(COSName.TYPE, COSName.ANNOT); 
     cosDict1.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget")); 
     cosDict1.setItem(COSName.T, new COSString("tx1")); 
     cosDict1.setItem(COSName.DA, new COSString(defaultAppearance)); 
//  cosDict1.setItem(COSName.V, new COSString("Test Value1")); 

     PDTextbox textbox = new PDTextbox(doc.getDocumentCatalog().getAcroForm(), cosDict1); 

     textbox.setValue("Test Value"); 

     page.getAnnotations().add(textbox.getWidget()); 
     acroForm.getFields().add(textbox); 

     doc.save("C:\\PDF\\SampleTextbox.pdf"); 
     doc.close(); 
    } 
}