java - 如何识别 PDF 文件是否包含表单域
问题描述
我们允许用户上传 PDF 文件供我们存储。我们警告用户在上传之前必须将 PDF 拼合,但许多人仍然上传包含表单字段的 PDF 文档。我们希望通过在上传到我们的存储之前验证 PDF 文件来防止这种情况。
我们正在使用 iText-5.1 将文件作为 byte[] 读取并使用 PdfReader 打开它。然后我们使用 AcroFields() 提取字段并测试是否存在。目前 getFields().size() 总是返回 0 [见下面的代码],即使我知道包含表单字段的测试 PDF 也是如此。
PdfReader reader = new PdfReader(bytes);
AcroFields fields = reader.getAcroFields()
boolean hasFormFields =
(fields != null && fields.getFields() != null && fields.getFields().size() > 0);
if (hasFormFields) {
// Report Error to User - throw exception, etc.
}
当 PDF 包含表单字段元素时,我希望 getFields().size() 大于 0。是否有其他方法可以使用 Java 和 iText 识别表单字段?
解决方案
您使用了正确的方法来识别(有效的)PDF 文件是否包含表单域。您描述的问题是如何处理不符合标准的 PDF 文件,这些文件也包含表单字段但确实存在一些问题,例如缺少 AcroField 字典、缺少字段数组或其他。你有三种可能:
- 忽略这些情况,因为这些是边缘情况
- 确定问题(例如使用 Acrobat Preflight)并编写一个方法来检查这些情况。您可以在下面找到一个示例,其中我编写了一个方法来识别缺少
Fields
数组的文档。 - 只需将所有上传的文件展平即可。
以下代码检查您的方法返回 true 但仍包含表单字段的文档。这些字段也将显示在 *dobe 阅读器中。
public boolean containsFormFields2() {
AcroFields acroFields = reader.getAcroFields();
if (acroFields.getFields() == null || acroFields.getFields().size() == 0) {
// recheck "manually"
for (int i = 1; i <= super.reader.getNumberOfPages(); i++) {
PdfDictionary page = super.reader.getPageN(i);
PdfArray annots = page.getAsArray(PdfName.ANNOTS);
if (annots != null) {
// check for form fields in general
for (int j = 0; j < annots.size(); j++) {
PdfDictionary po2 = (PdfDictionary) annots.getDirectObject(j);
// FT key only exists for form fields
PdfName type = (PdfName) po2.get(PdfName.FT);
if (type != null) {
return true;
}
}
}
}
return false;
}
else{
return true;
}
}
推荐阅读
- javascript - 如何使用 Moment.js 在年份和月份中获取两个日期之间的差异?
- botframework - 如何从网络聊天中隐藏用户消息但从后面发送?
- javascript - 我无法更改状态中的数组
- c - 在这种情况下是否可以强制 crypt 返回 NULL?
- node.js - 使用预签名 URL 将文件放入 S3 存储桶在本地工作的服务器上失败
- ruby - 有没有办法访问在块外的块内定义的局部变量?
- r - 在一个国家/地区生成随机坐标
- r - 在 R 数据框中转换间隔外连接 SQL
- java - 当有大量常量时,定义常量的正确方法是什么?
- python - 将负 Sobel 梯度值转换为 0 到 6.28 范围