Как заменить отсутствующий шрифт при заполнении формы с помощью PDFBox? - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь заполнить кучу форм PDF, используя PDFBox 2.0.8.Для некоторых документов я получаю следующую ошибку при установке значения PDTextField:

java.io.IOException: Could not find font: /ArialMT

Очевидно, что шрифт неправильно внедрен, как это часто бывает с проприетарными шрифтами Microsoft.

Как я могу сказатьPDFBox, чтобы заменить шрифт, например, «нормальным» Arial или другим шрифтом?Установка поля DA DA "/Helv 0 tf 0 g" привела к исключению NullPointerException.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Основываясь на комментариях Тилмана Хаушерра, я создал первое исправление, работающее независимо от операционной системы (в моем случае это Linux).

acroForm.defaultResources.put(COSName.getPDFName("ArialMT"),
    PDType0Font.load (pdDocument, this.javaClass.classLoader.getResourceAsStream("fonts/ARIALMT.ttf"), false))

Это будет работать только для этого конкретного шрифта,хоть.Чего еще не хватает - и на самом деле это было основным намерением моего вопроса - это возможность указать PDFBox использовать определенный шрифт, соответственно.DA, если требуемый шрифт не может быть предоставлен.

После того, как Тилман снова пришел на помощь, я теперь могу представить полное решение.Опять же, это Котлин, а не Java:

PDDocument.load(file).use { pdDocument ->
    val acroForm = pdDocument.documentCatalog.acroForm
    acroForm.defaultResources.put(COSName.getPDFName("ArialMT"),
            PDType0Font.load (pdDocument, this.javaClass.classLoader.getResourceAsStream("fonts/ARIALMT.ttf"), false))
    val pdField: PDField? = acroForm.getField(fieldname)
    val value = ...
    when (pdField) {
        is PDCheckBox -> {
            if (value is Boolean) {
                when (value) {
                    true -> pdField.check()
                    false -> pdField.unCheck()
                }
            } else {
                log.error("RENDER_FORM: Need Boolean for ${pdField.fullyQualifiedName} but got $value")
            }
        }
        is PDTextField -> {
            try {
                pdField.value = value?.toString() ?: ""
            } catch (ioException: IOException) {
                pdField.cosObject.setString(COSName.DA, "/Helv 0 Tf 0 g")
                pdField.value = value?.toString() ?: ""
                log.error("RENDER_FORM: Writing text field failed: ${ioException.message}")
            }
        }
        null -> {
            log.error("RENDER_FORMULAR: Formfield $fieldname does not exist in $name")
        }
        else -> log.error("RENDER_FORMULAR: Formfield $pdField ($fieldname) is of unhandled type ${pdField.fieldType}")
    }

    val stream = ByteArrayOutputStream()
    pdDocument.save(stream)
    pdDocument.close()
    return stream.toByteArray()
}
0 голосов
/ 31 мая 2018

Добавить «ArialMT» к ресурсам по умолчанию:

try (PDDocument doc = PDDocument.load(new File("F2_Datenblatt_022015.pdf")))
{
    PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
    PDField field = acroForm.getField("Vorname_Name");

    // fails with IOException as described in question
    //field.setValue("Tilman Hausherr");

    // Method 1, just add type1 Helvetica (allows only WinAnsiEncoding glyphs)
    //acroForm.getDefaultResources().put(COSName.getPDFName("ArialMT"), PDType1Font.HELVETICA);

    // Method 2, add the full Arial font (allows for more different glyphs)
    // important: use the method that switches off subsetting
    acroForm.getDefaultResources().put(
        COSName.getPDFName("ArialMT"), 
        PDType0Font.load(doc, new FileInputStream("c:/windows/fonts/arial.ttf"), false));


    field.setValue("Tilman Hausherr");

    doc.save("F2_Datenblatt_022015-mod.pdf");
}

Обновление: оказалось, что код в вопросе тоже работал бы с файлом - почти.Это «Tf», а не «tf», поэтому строка была бы «/ Helv 0 Tf 0 g».Мы исследуем, как избежать NPE и получить значимое исключение.

...