在这里您可以download pdf使用一个acroform字段,他的大小恰好是427Kb
如果我删除此唯一字段,则文件仅为3Kb,请为什么会发生这种情况? 我尝试使用PDF Debugger进行分析,对我来说似乎没有什么奇怪的。
答案 0 :(得分:2)
在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默认资源字体。
更新: 以下是一些将Heal替换为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");
您会得到一个例外。
可以在this answer中找到替换字体的更多常规代码。