在这里,您可以下载 一个acroform字段的pdf,其大小恰好是427Kb
如果我删除此唯一字段,则文件仅为3Kb,请为什么会发生这种情况?我尝试使用PDF Debugger进行分析,但似乎没有任何异常。
在acroform默认资源中有一个嵌入的“ Arial”字体,请参见Root/AcroForm/DR/Font/Arial/FontDescriptor/FontFile2。
您或创建PDF的人无缘无故地添加了它。该字体未使用/未引用。对于acroform默认资源,您可以检查每个字段的/ DA条目(默认外观)是否包含字体名称。
当您以某种方式删除字段时,还从acroForm默认资源中删除了字体。(您并未写出删除方式)
这是一些执行此操作的代码(大多数情况下都缺少空检查):
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm(); PDResources defaultResources = acroForm.getDefaultResources(); COSDictionary fontDict = (COSDictionary) defaultResources.getCOSObject().getDictionaryObject(COSName.FONT); List<String> defaultAppearances = new ArrayList<>(); List<COSName> fontDeletionList = new ArrayList<>(); for (PDField field : acroForm.getFieldTree()) { if (field instanceof PDVariableText) { PDVariableText vtField = (PDVariableText) field; defaultAppearances.add(vtField.getDefaultAppearance()); } } for (COSName fontName : defaultResources.getFontNames()) { if (COSName.HELV.equals(fontName) || COSName.ZA_DB.equals(fontName)) { // Adobe default, always keep continue; } boolean found = false; for (String da : defaultAppearances) { if (da != null && da.contains("/" + fontName.getName())) { found = true; break; } } System.out.println(fontName + ": " + found); if (!found) { fontDeletionList.add(fontName); } } System.out.println("deletion list: " + fontDeletionList); for (COSName fontName : fontDeletionList) { fontDict.removeItem(fontName); }
生成的文件现在为5KB。
我还没有检查注释。其中一些还具有/ DA字符串,但不清楚在重建缺失的外观流时是否使用acroform默认资源字体。
更新:这是一些其他代码,用Helv替换Arial:
for (PDField field : acroForm.getFieldTree()) { if (field instanceof PDVariableText) { PDVariableText vtField = (PDVariableText) field; String defaultAppearance = vtField.getDefaultAppearance(); if (defaultAppearance.startsWith("/Arial")) { vtField.setDefaultAppearance("/Helv " + defaultAppearance.substring(7)); vtField.getWidgets().get(0).setAppearance(null); // this removes the font usage vtField.setValue(vtField.getValueAsString()); } defaultAppearances.add(vtField.getDefaultAppearance()); } }
请注意,这可能不是一个好主意,因为标准的14种字体只有有限的字符。尝试
vtField.setValue("Ayşe");
然后您会得到一个例外。