用中文填写的PDF字段出现乱码问题

4
我正在尝试使用fdf或xfdf填写pdf字段中的中文字符。
目前为止,我已经尝试了pdftk、mcpdf、pdfbox和fpdm。它们都可以将字符输入到字段中,但是它们不会显示。当我单击字段进行编辑时,字符会按预期显示,但是当我再次单击字段离开时,它们就消失了。如果我输入英文,则显示不正确,例如“hello”变成了“IFMMP”。
这一切都让我怀疑这是字体/字符映射的问题,我尝试将完整字体嵌入pdf中,但没有任何改变。我已经在计算机上安装了字体,但仍然无济于事。
如果我在Acrobat中编辑pdf并填写字段,则可以轻松接受中文字符,并且我可以在阅读器中查看pdf。我已经尝试在同一台Windows机器上使用命令行中的pdftk,但我遇到了同样的问题。
我需要在Linux环境中工作,并最好使用Python或通过命令行脚本实现,但实际上,在这一点上,我只想看到它起作用!我已经附上了示例pdf、fdf、xfdf和它创建的输出,如果能提供任何帮助,将不胜感激,因为我已经没有更多的想法了。我一直在使用以下命令:
"pdftk test_form.pdf fill_form test.xfdf output output.pdf verbose"

https://drive.google.com/folderview?id=0B6ExNaWGFzvnfnJHSC1ZdXhSU2RQVENjYW56UkZyYWJMdWhZTkpQYkZBcUs0Tjhjb0NITVE&usp=sharing


你是否已经从填写正确的表单中导出,并将该(X)FDF与您拥有的进行了比较? - Max Wyss
我已经将正确填写的表单导出为 FDF,然后尝试使用它来填充相同的表单,并且出现了相同的错误。 - Matthew Wise
好的,我之所以问这个是为了确保FDF确实是正确的,这显然是正确的。如果没有任何免费/开源软件可用,并且确实需要一些投资,你可以考虑Appligent的FDFMerge(可能先联系他们了解具体情况)。 - Max Wyss
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Matthew Wise
1个回答

4
当填写表单字段时,该字段的值将被填充,并且(可选)会生成反映新设置值的表单字段的视觉外观。因此,您在单击表单字段时看到值的原因是该字段的值将被显示,但只要该字段未被激活,就会使用该字段的外观。
如果您尝试使用PDFBox 1.8设置值,则可以尝试使用PDFBox 2.0,因为现在它支持Unicode并重新生成外观。
您还需要确保在填写表单的系统上可用您在表单中使用的字体。否则,使用PDFBox 2.0可能会出现类似于错误消息的情况。
Warning: Using fallback font 'TimesNewRomanPSMT' for 'MingLiU'
Exception in thread "main" java.lang.IllegalArgumentException: No glyph for U+5185 in font MingLiU

由于系统中没有MingLiU字体,它被替换为TimesNewRomanPSMT,但该字体缺少所需字符。

作为另一种解决方案,您还可以指示Adobe Reader在打开表单时为您计算外观,方法如下:

PDAcroForm form = doc.getDocumentCatalog().getAcroForm();
form.setNeedAppearances(true);

再次使用PDFBox 2.0

我已经用PDFBox 2创建了一个小样例,从零开始创建一个表单以测试它是否能处理中文文本。

// create a new PDF document
PDDocument doc = new PDDocument();
PDPage page = new PDPage();

// add a new AcroForm and add that to the document
PDAcroForm form = new PDAcroForm(doc);
doc.getDocumentCatalog().setAcroForm(form);

// Add and set the resources and default appearance at the form level
PDFont font = PDType0Font.load(doc, new File("/Library/Fonts/Arial Unicode.ttf"));
PDResources res = new PDResources();
COSName fontName = res.add(font);
form.setDefaultResources(res);
String da = "/" + fontName.getName() + " 12 Tf 0 g";
form.setDefaultAppearance(da);

// add a page to the document 
doc.addPage(page);

// add a form field to the form
PDTextField textBox = new PDTextField(form);
textBox.setPartialName("Chinese");
form.getFields().add(textBox);

// specify the annotation associated with the field
// and add it to the page
PDAnnotationWidget widget = textBox.getWidget();
PDRectangle rect = new PDRectangle(100f,300f,120f,350f);
widget.setRectangle(rect);
page.getAnnotations().add(widget);

// set the field value
textBox.setValue("木兰辞");
doc.save("ChineseOut.pdf");

这个工作得很好。我也测试了你所使用的字体,不幸的是,MingLiU是一个TrueType集合,PDFBox在那个时候无法处理。


1
非常感谢您的帮助,您为我节省了大量搜索的时间。 我会研究一下,你对外观的评论让我发现了pdftk中need_appearances标志的需求,虽然在Linux中无法正确地填充表单以供查看,但是可以在Windows上使用Adobe Reader加载。 它也不能正确地压平它,我希望有一种可行的方法可以使用PDFBox或其他程序来压平pdf文件。 再次感谢。 - Matthew Wise
1
将表单展平是一个不同的问题,这意味着要从文档中删除表单字段和小部件,并使字段外观成为页面内容的一部分。这个问题已经在这里得到了回答:https://dev59.com/aGYq5IYBdhLWcg3weQgy - Maruan Sahyoun
很好,目前我正在使用来自https://repository.jboss.org/nexus/content/groups/public/org/apache/pdfbox/pdfbox-app/2.0.0-SNAPSHOT/的pdfbox-app,因为它包含相关依赖项。我试图使用您提供的脚本作为概念验证,但是当它到达textBox.setValue时,我得到了一个NullPointerException:在org.apache.pdfbox.pdmodel.interactive.form.PDVariableText.getDefaultAppearance(PDVariableText.java:86)。您有其他推荐的jar吗?由于我已经有一段时间没有编写Java代码了,所以如果我错过了一些明显的东西,请谅解。 - Matthew Wise
是的,我先尝试了那个,但是我该如何获取匹配的字体框和快照的XMP框版本呢?我应该从主干构建自己的版本吗? - Matthew Wise
请查看http://repository.apache.org/content/groups/snapshots/org/apache/pdfbox/,您可以从那里下载pdfbox-app(方便,因为它具有所有依赖项)或单独的库。 - Maruan Sahyoun
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接