如何找到并列出 acroform .pdf 中可编辑字段的内部字段标签?
How can the internal field labels of the editable fields in an acroform .pdf be found and listed?
如何找到并列出 acroform .pdf 中可编辑字段的内部字段标签?
这是必需的,以便它们可以用于以编程方式填写 .pdf。
我想使用 pdfBox 或 iText,但是 .pdf 很复杂,而且似乎两者都无法完成此任务。
是否存在查找并列出可编辑字段的内部字段标签的软件或代码?
非常感谢任何帮助,谢谢。
请参考以下代码解决
public class PDFBOX {
public static void main(String[] args) throws IOException {
PDDocument fdeb = null;
File pdfFile = new File("C:\Users\pc\Desktop\Req-form.pdf");
fdeb = PDDocument.load(pdfFile);
PDDocumentCatalog pdCatalog = fdeb.getDocumentCatalog();
PDAcroForm pdAcroForm = pdCatalog.getAcroForm();
// Text fields
PDField firstName = pdAcroForm.getField("firstName");
firstName.setValue("firstName");
fdeb.save("C:\Users\Desktop\Test.pdf");
fdeb.close();
}
}
不幸的是,这个问题并不完全清楚。特别是术语“内部标签”非常模糊。在此答案中,我假设他的意思是“完全限定的字段名称”,它由字段的部分字段名称及其所有祖先构成,如 PDF 规范(ISO 32000-1)第 12.7.3.2 节所述。如果这不是要求的“内部标签”,请正确定义该术语。
还不清楚代码应该如何“将它们组织成一个对象”;我假设将它们添加到列表中是合格的。
iText 7
在 iText 7.0.1 中,您可以使用以下方法检索表单字段的完全限定名称列表:
List<String> getFormFieldNames(PdfDocument pdfDocument)
{
PdfAcroForm pdfAcroForm = PdfAcroForm.getAcroForm(pdfDocument, false);
if (pdfAcroForm == null)
return Collections.emptyList();
List<String> result = new ArrayList<>(pdfAcroForm.getFormFields().keySet());
return result;
}
(iText ShowFormFieldNames 方法 getFormFieldNames
)
PDFBox 2
使用 PDFBox 2.0.3,您可以使用以下方法检索表单字段的完全限定名称列表:
List<String> getFormFieldNames(PDDocument pdDocument)
{
PDAcroForm pdAcroForm = pdDocument.getDocumentCatalog().getAcroForm();
if (pdAcroForm == null)
return Collections.emptyList();
List<String> result = new ArrayList<>();
for (PDField pdField : pdAcroForm.getFieldTree())
{
if (pdField instanceof PDTerminalField)
{
result.add(pdField.getFullyQualifiedName());
}
}
return result;
}
(PDFBox ShowFormFieldNames 方法 getFormFieldNames
)
或者(需要Java 8)更花哨
List<String> getFormFieldNamesFancy(PDDocument pdDocument)
{
PDAcroForm pdAcroForm = pdDocument.getDocumentCatalog().getAcroForm();
if (pdAcroForm == null)
return Collections.emptyList();
return StreamSupport.stream(pdAcroForm.getFieldTree().spliterator(), false)
.filter(field -> (field instanceof PDTerminalField))
.map(field -> field.getFullyQualifiedName())
.collect(Collectors.toList());
}
(PDFBox ShowFormFieldNames 方法 getFormFieldNamesFancy
)
iText 可用于列出 acroform .pdf 中的内部字段。这是一个命令行程序,可以用 IntelliJ 构建,可以做到这一点:
https://github.com/powerblue/use_iText_to_get_internal_fields
package fr.jp.pdf;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FormParser {
public static final String VERSION = "16.10.13.1";
private static final Logger LOGGER = LoggerFactory.getLogger(FormParser.class);
public static final String PARAM_KEY__GET_LIST = "-LIST_FIELDS";
private static final String MSG_HELP = "usage:\n> java -cp $CLASSPATH fr.jp.pdf.FormParser -LIST_FIELDS pdf_file\n";
public static void main(String[] args) {
LOGGER.debug("Start, v{}", VERSION);
FormParser formParser = new FormParser();
try {
String mode = formParser.getMode(args);
switch (mode) {
case PARAM_KEY__GET_LIST:
int idx_file_name = (args[0].equals(PARAM_KEY__GET_LIST)) ? 1 : 0;
formParser.printFields(args[idx_file_name]);
break;
default:
printHelp();
}
} catch (Exception e) {
LOGGER.error("Problem: ", e);
}
LOGGER.debug("Finish");
}
private String getMode(String[] args) {
LOGGER.debug("Start with {}", Arrays.asList(args));
String mode = "UNKNOWN";
if (args.length > 0) {
if ((Arrays.binarySearch(args, PARAM_KEY__GET_LIST) >= 0) && (args.length == 2)) {
mode = PARAM_KEY__GET_LIST;
} else {
LOGGER.warn("Invoke with unknown params: {}", Arrays.asList(args));
}
} else {
LOGGER.warn("Invoke with empty arguments! Don't run.");
}
LOGGER.debug("Finish, return: [{}]", mode);
return mode;
}
private void printFields(String file_name) throws IOException {
LOGGER.debug("Start for [{}]", file_name);
LOGGER.trace("Try open PDF file: [{}]", file_name);
URL fileURL = super.getClass().getClassLoader().getResource(file_name);
if (fileURL == null) throw new IOException("NOT FOUND File \"" + file_name + "\"");
PdfReader pdfReader = null;
try {
String src = fileURL.getFile();
LOGGER.debug("Try open PDF file: [{}]", src);
pdfReader = new PdfReader(src);
if (pdfReader == null) throw new IOException("Problem iText with load PdfReader!");
LOGGER.debug("PdfReader open succ");
AcroFields acroFields = pdfReader.getAcroFields();
LOGGER.debug("AcroFields form getted: [{}]", acroFields);
if (acroFields == null) throw new IOException("AcroFields not exist!");
Map<String, AcroFields.Item> fields = acroFields.getFields();
LOGGER.debug("Field count: [{}]", fields.size());
int i = 0;
for (String field_key : fields.keySet()) {
AcroFields.Item field = fields.get(field_key);
LOGGER.info("{}. [Page:{}, tabOrder:{}, Field.size:{}, Key:{}] ", ++i, field.getPage(0), field.getTabOrder(0), field.size(), field_key);
}
} catch (IOException e) {
LOGGER.error("Problem: ", e);
} finally {
if (pdfReader != null)
pdfReader.close();
LOGGER.trace("PdfReader closed");
}
LOGGER.debug("Finish processing PDF doc [{}]", file_name);
}
/**
* parse key=value array as single String
*
* @param key_values_string - key=value array as single String
* @return -
*/
public static Hashtable<String, String> prepareData(String key_values_string) throws ParseException {
LOGGER.debug("Invoke with [{}]", key_values_string);
Hashtable<String, String> result = new Hashtable<>();
String[] key_values_arr = key_values_string.split(";");
LOGGER.trace("Found the {} pair key=value", key_values_arr.length);
for (String key_value : key_values_arr) {
String[] key_value_pair_arr = key_value.split("=");
if (key_value_pair_arr.length != 2) {
throw new ParseException("Wrong format \"key=value\" pair: " + key_value, 0);
}
if (result.containsKey(key_value_pair_arr[0])) {
throw new ParseException("Found duplicate Key: " + key_value_pair_arr[0], 0);
}
result.put(key_value_pair_arr[0], key_value_pair_arr[1]);
}
return result;
}
private static void printHelp() {
LOGGER.debug("Invoke");
System.out.println(MSG_HELP);
}
}
如何找到并列出 acroform .pdf 中可编辑字段的内部字段标签?
这是必需的,以便它们可以用于以编程方式填写 .pdf。
我想使用 pdfBox 或 iText,但是 .pdf 很复杂,而且似乎两者都无法完成此任务。
是否存在查找并列出可编辑字段的内部字段标签的软件或代码?
非常感谢任何帮助,谢谢。
请参考以下代码解决
public class PDFBOX {
public static void main(String[] args) throws IOException {
PDDocument fdeb = null;
File pdfFile = new File("C:\Users\pc\Desktop\Req-form.pdf");
fdeb = PDDocument.load(pdfFile);
PDDocumentCatalog pdCatalog = fdeb.getDocumentCatalog();
PDAcroForm pdAcroForm = pdCatalog.getAcroForm();
// Text fields
PDField firstName = pdAcroForm.getField("firstName");
firstName.setValue("firstName");
fdeb.save("C:\Users\Desktop\Test.pdf");
fdeb.close();
}
}
不幸的是,这个问题并不完全清楚。特别是术语“内部标签”非常模糊。在此答案中,我假设他的意思是“完全限定的字段名称”,它由字段的部分字段名称及其所有祖先构成,如 PDF 规范(ISO 32000-1)第 12.7.3.2 节所述。如果这不是要求的“内部标签”,请正确定义该术语。
还不清楚代码应该如何“将它们组织成一个对象”;我假设将它们添加到列表中是合格的。
iText 7
在 iText 7.0.1 中,您可以使用以下方法检索表单字段的完全限定名称列表:
List<String> getFormFieldNames(PdfDocument pdfDocument)
{
PdfAcroForm pdfAcroForm = PdfAcroForm.getAcroForm(pdfDocument, false);
if (pdfAcroForm == null)
return Collections.emptyList();
List<String> result = new ArrayList<>(pdfAcroForm.getFormFields().keySet());
return result;
}
(iText ShowFormFieldNames 方法 getFormFieldNames
)
PDFBox 2
使用 PDFBox 2.0.3,您可以使用以下方法检索表单字段的完全限定名称列表:
List<String> getFormFieldNames(PDDocument pdDocument)
{
PDAcroForm pdAcroForm = pdDocument.getDocumentCatalog().getAcroForm();
if (pdAcroForm == null)
return Collections.emptyList();
List<String> result = new ArrayList<>();
for (PDField pdField : pdAcroForm.getFieldTree())
{
if (pdField instanceof PDTerminalField)
{
result.add(pdField.getFullyQualifiedName());
}
}
return result;
}
(PDFBox ShowFormFieldNames 方法 getFormFieldNames
)
或者(需要Java 8)更花哨
List<String> getFormFieldNamesFancy(PDDocument pdDocument)
{
PDAcroForm pdAcroForm = pdDocument.getDocumentCatalog().getAcroForm();
if (pdAcroForm == null)
return Collections.emptyList();
return StreamSupport.stream(pdAcroForm.getFieldTree().spliterator(), false)
.filter(field -> (field instanceof PDTerminalField))
.map(field -> field.getFullyQualifiedName())
.collect(Collectors.toList());
}
(PDFBox ShowFormFieldNames 方法 getFormFieldNamesFancy
)
iText 可用于列出 acroform .pdf 中的内部字段。这是一个命令行程序,可以用 IntelliJ 构建,可以做到这一点:
https://github.com/powerblue/use_iText_to_get_internal_fields
package fr.jp.pdf;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FormParser {
public static final String VERSION = "16.10.13.1";
private static final Logger LOGGER = LoggerFactory.getLogger(FormParser.class);
public static final String PARAM_KEY__GET_LIST = "-LIST_FIELDS";
private static final String MSG_HELP = "usage:\n> java -cp $CLASSPATH fr.jp.pdf.FormParser -LIST_FIELDS pdf_file\n";
public static void main(String[] args) {
LOGGER.debug("Start, v{}", VERSION);
FormParser formParser = new FormParser();
try {
String mode = formParser.getMode(args);
switch (mode) {
case PARAM_KEY__GET_LIST:
int idx_file_name = (args[0].equals(PARAM_KEY__GET_LIST)) ? 1 : 0;
formParser.printFields(args[idx_file_name]);
break;
default:
printHelp();
}
} catch (Exception e) {
LOGGER.error("Problem: ", e);
}
LOGGER.debug("Finish");
}
private String getMode(String[] args) {
LOGGER.debug("Start with {}", Arrays.asList(args));
String mode = "UNKNOWN";
if (args.length > 0) {
if ((Arrays.binarySearch(args, PARAM_KEY__GET_LIST) >= 0) && (args.length == 2)) {
mode = PARAM_KEY__GET_LIST;
} else {
LOGGER.warn("Invoke with unknown params: {}", Arrays.asList(args));
}
} else {
LOGGER.warn("Invoke with empty arguments! Don't run.");
}
LOGGER.debug("Finish, return: [{}]", mode);
return mode;
}
private void printFields(String file_name) throws IOException {
LOGGER.debug("Start for [{}]", file_name);
LOGGER.trace("Try open PDF file: [{}]", file_name);
URL fileURL = super.getClass().getClassLoader().getResource(file_name);
if (fileURL == null) throw new IOException("NOT FOUND File \"" + file_name + "\"");
PdfReader pdfReader = null;
try {
String src = fileURL.getFile();
LOGGER.debug("Try open PDF file: [{}]", src);
pdfReader = new PdfReader(src);
if (pdfReader == null) throw new IOException("Problem iText with load PdfReader!");
LOGGER.debug("PdfReader open succ");
AcroFields acroFields = pdfReader.getAcroFields();
LOGGER.debug("AcroFields form getted: [{}]", acroFields);
if (acroFields == null) throw new IOException("AcroFields not exist!");
Map<String, AcroFields.Item> fields = acroFields.getFields();
LOGGER.debug("Field count: [{}]", fields.size());
int i = 0;
for (String field_key : fields.keySet()) {
AcroFields.Item field = fields.get(field_key);
LOGGER.info("{}. [Page:{}, tabOrder:{}, Field.size:{}, Key:{}] ", ++i, field.getPage(0), field.getTabOrder(0), field.size(), field_key);
}
} catch (IOException e) {
LOGGER.error("Problem: ", e);
} finally {
if (pdfReader != null)
pdfReader.close();
LOGGER.trace("PdfReader closed");
}
LOGGER.debug("Finish processing PDF doc [{}]", file_name);
}
/**
* parse key=value array as single String
*
* @param key_values_string - key=value array as single String
* @return -
*/
public static Hashtable<String, String> prepareData(String key_values_string) throws ParseException {
LOGGER.debug("Invoke with [{}]", key_values_string);
Hashtable<String, String> result = new Hashtable<>();
String[] key_values_arr = key_values_string.split(";");
LOGGER.trace("Found the {} pair key=value", key_values_arr.length);
for (String key_value : key_values_arr) {
String[] key_value_pair_arr = key_value.split("=");
if (key_value_pair_arr.length != 2) {
throw new ParseException("Wrong format \"key=value\" pair: " + key_value, 0);
}
if (result.containsKey(key_value_pair_arr[0])) {
throw new ParseException("Found duplicate Key: " + key_value_pair_arr[0], 0);
}
result.put(key_value_pair_arr[0], key_value_pair_arr[1]);
}
return result;
}
private static void printHelp() {
LOGGER.debug("Invoke");
System.out.println(MSG_HELP);
}
}