为什么 PDFBox 会覆盖多个字段,即使它们与 fullyQualifiedName 不匹配? (科特林 Android)
Why is PDFBox overwriting multiple Fields, even when they don't match the fullyQualifiedName? (Kotlin Android)
我正在使用 com.tom_roush:pdfbox-android:1.8.10.1 版本的 PDFBox。
我有以下代码。
val skillList = listOf<String>("Athletics","Acrobatics","Sleight of Hand", "Stealth","Acrana", "History","Investigation","Nature", "Religion", "Animal Handling", "Insight", "Medicine", "Perception", "Survival", "Deception", "Intimidation", "Performance", "Persuasion"
private fun getField(acroForm:PDAcroForm,name:String): PDTextField {
return acroForm.getField(name) as PDTextField
}
var temp = 0
skillList.forEach {
val field = getField(acroForm,it.name)
temp += 1
field.value = temp.toString()
}
这是 PDF 的 link。
PDF in question
我的问题是我的最终 PDF(所有具有与上面列表匹配的唯一名称的字段),其中许多设置为 18 遍中的第 17 遍。我做错了什么?
这是 PDFBox(1.8.x 和 2.x)在填写 PDF 表单时的一个错误,只有在原始表单中多个字段共享相同的 XObject 作为外观流时才会发生。
详细
您的原始文档包含许多空白文本字段。它们的几个子集共享相同的外观流,例如“体育”和“宗教”:
如您所见,它们都共享 PDF 对象 479 中的 XObject。
当PDFBox填写表单值时,它首先将“Athletics”的值设置为“1”,同时更新外观XObject以显示“1”,然后将“Religion”的值设置为“ 9”并更新外观 XObject 以显示“9”。最终结果:在查看器中,“Athletics”和“Religion”都显示“9”作为值。
问题是 PDFBox 假定它在设置表单字段的值时可以简单地更新 现有的外观流。实际上它必须 替换 它,如果它碰巧是间接的,也可能是 AP 字典,因为它也可能被共享。
解决方法
您的解决方法是在设置字段之前删除现有的空白外观:
field.getDictionary().removeItem(COSName.AP)
field.value = temp.toString()
(可能该行在 Kotlin 中可以缩短为 field.dictionary.removeItem(COSName.AP)
但我对 Kotlin 几乎一无所知...)
背景
有人可能想知道在此处的源 PDF 中找到的构造(即多个文本字段共享的外观流)是否完全有效。但实际上我在 PDF 规范中找不到任何禁止这样做的内容,相反,可以采取以下关于一般注释的部分(表单字段小部件是特殊注释)来明确允许它:
A given annotation dictionary shall be referenced from the Annots array of only one page. This requirement applies only to the annotation dictionary itself, not to subsidiary objects, which may be shared among multiple annotations.
(ISO 32000-1 和 ISO 32000-2,第 12.5.2 节“注释词典”)
我正在使用 com.tom_roush:pdfbox-android:1.8.10.1 版本的 PDFBox。
我有以下代码。
val skillList = listOf<String>("Athletics","Acrobatics","Sleight of Hand", "Stealth","Acrana", "History","Investigation","Nature", "Religion", "Animal Handling", "Insight", "Medicine", "Perception", "Survival", "Deception", "Intimidation", "Performance", "Persuasion"
private fun getField(acroForm:PDAcroForm,name:String): PDTextField {
return acroForm.getField(name) as PDTextField
}
var temp = 0
skillList.forEach {
val field = getField(acroForm,it.name)
temp += 1
field.value = temp.toString()
}
这是 PDF 的 link。 PDF in question 我的问题是我的最终 PDF(所有具有与上面列表匹配的唯一名称的字段),其中许多设置为 18 遍中的第 17 遍。我做错了什么?
这是 PDFBox(1.8.x 和 2.x)在填写 PDF 表单时的一个错误,只有在原始表单中多个字段共享相同的 XObject 作为外观流时才会发生。
详细
您的原始文档包含许多空白文本字段。它们的几个子集共享相同的外观流,例如“体育”和“宗教”:
如您所见,它们都共享 PDF 对象 479 中的 XObject。
当PDFBox填写表单值时,它首先将“Athletics”的值设置为“1”,同时更新外观XObject以显示“1”,然后将“Religion”的值设置为“ 9”并更新外观 XObject 以显示“9”。最终结果:在查看器中,“Athletics”和“Religion”都显示“9”作为值。
问题是 PDFBox 假定它在设置表单字段的值时可以简单地更新 现有的外观流。实际上它必须 替换 它,如果它碰巧是间接的,也可能是 AP 字典,因为它也可能被共享。
解决方法
您的解决方法是在设置字段之前删除现有的空白外观:
field.getDictionary().removeItem(COSName.AP)
field.value = temp.toString()
(可能该行在 Kotlin 中可以缩短为 field.dictionary.removeItem(COSName.AP)
但我对 Kotlin 几乎一无所知...)
背景
有人可能想知道在此处的源 PDF 中找到的构造(即多个文本字段共享的外观流)是否完全有效。但实际上我在 PDF 规范中找不到任何禁止这样做的内容,相反,可以采取以下关于一般注释的部分(表单字段小部件是特殊注释)来明确允许它:
A given annotation dictionary shall be referenced from the Annots array of only one page. This requirement applies only to the annotation dictionary itself, not to subsidiary objects, which may be shared among multiple annotations.
(ISO 32000-1 和 ISO 32000-2,第 12.5.2 节“注释词典”)