使用 PDFBOX 生成的 PDF 中保存的文本字段值未正确显示
Saved Text Field value is not displayed properly in PDF generated using 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("Test Value"); 设置值;方法,但它给出如下所示的错误:
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(COSName.V, new COSString("Test Value1"));
然后在 Adobe Reader 中,textBox 的值未正确填充。
我必须单击文本框,然后只显示值,一旦我离开该字段,值又会变得不可见。
问题#3
为了解决问题 #2,我需要如下所示将 needAppearances 标志设置为 true,然后该字段值才能在 PDF 中正确显示。但是在这个解决方案之后,一旦用户更改了字段值,我就无法 extract/parse 返回 PDF 字段,我们再次解析这个 PDF。
注意:- Adobe Reader 中存在此问题,这里在打开 PDF 时会给出一些消息,例如 修复表单域。一旦我保存 PDF 并尝试解析 acroform 字段,发现所有字段都被重置或为空。 None 的字段名称或字段值可以提取。
所以使用 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。
在上面的问题中,我通过将页面资源添加到 acroform 并为文本使用了正确的默认外观字符串来修复问题 #1。现在我不需要将 needsAppearance 标志设置为 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();
}
}
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("Test Value"); 设置值;方法,但它给出如下所示的错误:
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(COSName.V, new COSString("Test Value1"));
然后在 Adobe Reader 中,textBox 的值未正确填充。 我必须单击文本框,然后只显示值,一旦我离开该字段,值又会变得不可见。
问题#3
为了解决问题 #2,我需要如下所示将 needAppearances 标志设置为 true,然后该字段值才能在 PDF 中正确显示。但是在这个解决方案之后,一旦用户更改了字段值,我就无法 extract/parse 返回 PDF 字段,我们再次解析这个 PDF。
注意:- Adobe Reader 中存在此问题,这里在打开 PDF 时会给出一些消息,例如 修复表单域。一旦我保存 PDF 并尝试解析 acroform 字段,发现所有字段都被重置或为空。 None 的字段名称或字段值可以提取。
所以使用 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。
在上面的问题中,我通过将页面资源添加到 acroform 并为文本使用了正确的默认外观字符串来修复问题 #1。现在我不需要将 needsAppearance 标志设置为 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();
}
}