Почему pdf содержит только одно поле - около 500 Кб - PullRequest
0 голосов
/ 03 апреля 2019

Здесь вы можете скачать pdf с одним полем acroform, и его размер точно равен 427Kb

Если я удаляю это уникальное поле, файл имеет размер только 3 КБ, почему это происходит, пожалуйста? Я попытался проанализировать с помощью PDF Debugger, и мне ничего не показалось странным.

enter image description here

1 Ответ

2 голосов
/ 04 апреля 2019

В ресурсах по умолчанию для 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);
    }

Полученный файл теперь имеет размер 5 КБ.

Я не проверил аннотации. В некоторых из них также есть строка / DA, но неясно, следует ли использовать шрифты ресурсов по умолчанию в acroform для восстановления отсутствующего потока внешнего вида.

Обновление: Вот дополнительный код для замены Arial на Helv:

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");

и вы получите исключение.

Более общий код для замены шрифта можно найти в этом ответе .

...