使用 PDFBox 填写表单时如何替换缺失的字体?

Chr*_*ich 3 java fonts pdfbox

我正在尝试使用 PDFBox 2.0.8 填写一堆 PDF 表单。对于某些文档,在设置 PDTextField 的值时出现以下错误:

java.io.IOException: Could not find font: /ArialMT
Run Code Online (Sandbox Code Playgroud)

显然,该字体未正确嵌入,就像 Microsoft 专有字体经常出现的情况一样。

我如何告诉 PDFBox 用“普通”Arial 或其他字体替换字体?将字段 DA 字符串设置为"/Helv 0 tf 0 g"导致 NullPointerException。

Chr*_*ich 5

根据 Tilman Hausherr 的评论,我构建了第一个修复程序,该修复程序独立于操作系统(在我的例子中是 Linux)工作。

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

不过,这仅适用于该特定字体。仍然缺少的 - 实际上是我问题的主要目的 - 是告诉 PDFBox 回退到特定字体的选项。如果无法提供所需的字体,则为 DA。

在蒂尔曼再次前来救援之后,我现在可以提出完整的解决方案。再次强调,这是 Kotlin,不是 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()
}
Run Code Online (Sandbox Code Playgroud)