You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache PDFBox自定义属性出现默认属性的原因及解决办法

问题描述

使用commons-logging-1.2.jar和pdfbox-2.0.27.jar(注:代码中使用PDFBox相关类,推测为pdfbox而非fontbox)读取PDF属性时,本应排除的CreationDate、ModDate、Title等属性仍出现在自定义属性列表中,通过if-else拦截无效。

代码示例

public List<String[]> readPDFProperties(String fileName, String filePath) {
        System.out.println("PDF");
        System.out.println(fileName);
        List<String[]> arrList = new ArrayList<>();
        try {

            PDDocument pdDocument = PDDocument.load(new FileInputStream(filePath));
            PDDocumentInformation pdDocumentInformation = pdDocument.getDocumentInformation();
            Set<String> set = pdDocumentInformation.getMetadataKeys();
            Iterator<String> iterator = set.iterator();

            while (iterator.hasNext()) {
                String value = iterator.next().trim();
                if (value.equalsIgnoreCase("Author") || value.equalsIgnoreCase("CreationDate") ||
                        value.equalsIgnoreCase("Creator") || value.equalsIgnoreCase("ModDate") ||
                        value.equalsIgnoreCase("Title") || value.equalsIgnoreCase("Trapped") ||
                        value.equalsIgnoreCase("Producer") || value.equalsIgnoreCase("Subject") ||
                        value.equalsIgnoreCase("Keywords") || value.equalsIgnoreCase("Config File")) {
                } else {
                    String creationDate = pdDocumentInformation.getCreationDate().getTime().toString() != null ? pdDocumentInformation.getCreationDate().getTime().toString() : "";
                    String modifiedDate = pdDocumentInformation.getModificationDate().getTime().toString() != null ? pdDocumentInformation.getModificationDate().getTime().toString() : "";
                    String[] arr = new String[14];

                    arr[0] = fileName;
                    arr[1] = pdDocumentInformation.getTitle() != null ? pdDocumentInformation.getTitle() : pdDocumentInformation.getCOSObject().getString("Title") != null ? pdDocumentInformation.getCOSObject().getString("Title") : "";
                    arr[2] = pdDocumentInformation.getSubject() != null ? pdDocumentInformation.getSubject() : pdDocumentInformation.getCOSObject().getString("Subject") != null ? pdDocumentInformation.getCOSObject().getString("Subject") : "";
                    arr[3] = pdDocumentInformation.getCOSObject().getString("Author") != null ? pdDocumentInformation.getCOSObject().getString("Author") : "";
                    arr[4] = "";
                    arr[5] = "";
                    arr[6] = "";
                    arr[7] = pdDocumentInformation.getKeywords() != null ? pdDocumentInformation.getKeywords() : pdDocumentInformation.getCOSObject().getString("Keywords") != null ? pdDocumentInformation.getCOSObject().getString("Keywords") : "";
                    arr[8] = ""; //9

                    arr[9] = value != null ? value : "";
                    arr[10] = pdDocumentInformation.getCOSObject().getString(value) != null ? pdDocumentInformation.getCOSObject().getString(value) : "";

                    arr[11] = creationDate;
                    arr[12] = modifiedDate;
                    arr[13] = ""; //3
                    arrList.add(arr);
                }
            }

            if (arrList.size() == 0) {
                String creationDate = pdDocumentInformation.getCreationDate().getTime().toString() != null ? pdDocumentInformation.getCreationDate().getTime().toString() : "";
                String modifiedDate = pdDocumentInformation.getModificationDate().getTime().toString() != null ? pdDocumentInformation.getModificationDate().getTime().toString() : "";
                String[] arr = new String[14];

                arr[0] = fileName;
                arr[1] = pdDocumentInformation.getTitle() != null ? pdDocumentInformation.getTitle() : pdDocumentInformation.getCOSObject().getString("Title") != null ? pdDocumentInformation.getCOSObject().getString("Title") : "";
                arr[2] = pdDocumentInformation.getSubject() != null ? pdDocumentInformation.getSubject() : pdDocumentInformation.getCOSObject().getString("Subject") != null ? pdDocumentInformation.getCOSObject().getString("Subject") : "";
                arr[3] = pdDocumentInformation.getCOSObject().getString("Author") != null ? pdDocumentInformation.getCOSObject().getString("Author") : "";
                arr[4] = "";
                arr[5] = "";
                arr[6] = "";
                arr[7] = pdDocumentInformation.getKeywords() != null ? pdDocumentInformation.getKeywords() : pdDocumentInformation.getCOSObject().getString("Keywords") != null ? pdDocumentInformation.getCOSObject().getString("Keywords") : "";
                arr[8] = ""; //9

                arr[9] = "";
                arr[10] = "";

                arr[11] = creationDate;
                arr[12] = modifiedDate;
                arr[13] = ""; //3
                arrList.add(arr);
            }
            pdDocument.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return arrList;
    }

CSV结果说明

CSV输出中,CreationDate、ModDate、Title等被标记为排除的属性,仍作为自定义属性条目出现,与预期不符。


问题根源
  1. 元数据键格式不匹配:PDFBox的getMetadataKeys()返回的键默认带/前缀(比如/CreationDate),而代码中直接用equalsIgnoreCase("CreationDate")匹配,导致拦截逻辑失效。
  2. 空指针风险隐藏:原代码中pdDocumentInformation.getCreationDate().getTime().toString()如果getCreationDate()返回null,会直接抛出空指针,后续逻辑无法正常执行。
  3. 判断逻辑冗余:用多个||拼接判断容易漏写或出错,且未处理键的前缀问题。

解决方案

1. 统一处理元数据键前缀

先去除键的/前缀,再做匹配:

String value = iterator.next().trim();
if (value.startsWith("/")) {
    value = value.substring(1);
}

2. 用集合存储排除键,简化判断

将需要排除的键存入HashSet,提升判断效率且易维护:

Set<String> excludedKeys = new HashSet<>(Arrays.asList(
    "Author", "CreationDate", "Creator", "ModDate",
    "Title", "Trapped", "Producer", "Subject", "Keywords", "Config File"
));

3. 修复空指针问题

安全获取日期字符串,避免直接链式调用导致空指针:

String creationDate = "";
if (pdDocumentInformation.getCreationDate() != null && pdDocumentInformation.getCreationDate().getTime() != null) {
    creationDate = pdDocumentInformation.getCreationDate().getTime().toString();
}

String modifiedDate = "";
if (pdDocumentInformation.getModificationDate() != null && pdDocumentInformation.getModificationDate().getTime() != null) {
    modifiedDate = pdDocumentInformation.getModificationDate().getTime().toString();
}

完整修正后的代码

public List<String[]> readPDFProperties(String fileName, String filePath) {
    System.out.println("PDF");
    System.out.println(fileName);
    List<String[]> arrList = new ArrayList<>();
    // 定义需要排除的属性键集合
    Set<String> excludedKeys = new HashSet<>(Arrays.asList(
        "Author", "CreationDate", "Creator", "ModDate",
        "Title", "Trapped", "Producer", "Subject", "Keywords", "Config File"
    ));

    try {
        PDDocument pdDocument = PDDocument.load(new FileInputStream(filePath));
        PDDocumentInformation pdDocumentInformation = pdDocument.getDocumentInformation();
        Set<String> set = pdDocumentInformation.getMetadataKeys();
        Iterator<String> iterator = set.iterator();

        while (iterator.hasNext()) {
            String value = iterator.next().trim();
            // 去除斜杠前缀
            if (value.startsWith("/")) {
                value = value.substring(1);
            }
            // 跳过排除的键
            if (excludedKeys.contains(value)) {
                continue;
            }

            // 安全获取日期
            String creationDate = "";
            if (pdDocumentInformation.getCreationDate() != null && pdDocumentInformation.getCreationDate().getTime() != null) {
                creationDate = pdDocumentInformation.getCreationDate().getTime().toString();
            }
            String modifiedDate = "";
            if (pdDocumentInformation.getModificationDate() != null && pdDocumentInformation.getModificationDate().getTime() != null) {
                modifiedDate = pdDocumentInformation.getModificationDate().getTime().toString();
            }

            String[] arr = new String[14];
            arr[0] = fileName;
            arr[1] = pdDocumentInformation.getTitle() != null ? pdDocumentInformation.getTitle() : 
                     (pdDocumentInformation.getCOSObject().getString("Title") != null ? pdDocumentInformation.getCOSObject().getString("Title") : "");
            arr[2] = pdDocumentInformation.getSubject() != null ? pdDocumentInformation.getSubject() : 
                     (pdDocumentInformation.getCOSObject().getString("Subject") != null ? pdDocumentInformation.getCOSObject().getString("Subject") : "");
            arr[3] = pdDocumentInformation.getCOSObject().getString("Author") != null ? pdDocumentInformation.getCOSObject().getString("Author") : "";
            arr[4] = "";
            arr[5] = "";
            arr[6] = "";
            arr[7] = pdDocumentInformation.getKeywords() != null ? pdDocumentInformation.getKeywords() : 
                     (pdDocumentInformation.getCOSObject().getString("Keywords") != null ? pdDocumentInformation.getCOSObject().getString("Keywords") : "");
            arr[8] = "";
            arr[9] = value != null ? value : "";
            // 获取COS属性时加回斜杠前缀
            arr[10] = pdDocumentInformation.getCOSObject().getString("/" + value) != null ? pdDocumentInformation.getCOSObject().getString("/" + value) : "";
            arr[11] = creationDate;
            arr[12] = modifiedDate;
            arr[13] = "";
            arrList.add(arr);
        }

        // 无自定义属性时的默认条目
        if (arrList.size() == 0) {
            String creationDate = "";
            if (pdDocumentInformation.getCreationDate() != null && pdDocumentInformation.getCreationDate().getTime() != null) {
                creationDate = pdDocumentInformation.getCreationDate().getTime().toString();
            }
            String modifiedDate = "";
            if (pdDocumentInformation.getModificationDate() != null && pdDocumentInformation.getModificationDate().getTime() != null) {
                modifiedDate = pdDocumentInformation.getModificationDate().getTime().toString();
            }

            String[] arr = new String[14];
            arr[0] = fileName;
            arr[1] = pdDocumentInformation.getTitle() != null ? pdDocumentInformation.getTitle() : 
                     (pdDocumentInformation.getCOSObject().getString("Title") != null ? pdDocumentInformation.getCOSObject().getString("Title") : "");
            arr[2] = pdDocumentInformation.getSubject() != null ? pdDocumentInformation.getSubject() : 
                     (pdDocumentInformation.getCOSObject().getString("Subject") != null ? pdDocumentInformation.getCOSObject().getString("Subject") : "");
            arr[3] = pdDocumentInformation.getCOSObject().getString("Author") != null ? pdDocumentInformation.getCOSObject().getString("Author") : "";
            arr[4] = "";
            arr[5] = "";
            arr[6] = "";
            arr[7] = pdDocumentInformation.getKeywords() != null ? pdDocumentInformation.getKeywords() : 
                     (pdDocumentInformation.getCOSObject().getString("Keywords") != null ? pdDocumentInformation.getCOSObject().getString("Keywords") : "");
            arr[8] = "";
            arr[9] = "";
            arr[10] = "";
            arr[11] = creationDate;
            arr[12] = modifiedDate;
            arr[13] = "";
            arrList.add(arr);
        }
        pdDocument.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return arrList;
}

额外说明

获取COS对象属性值时,需要把去除的斜杠加回去(pdDocumentInformation.getCOSObject().getString("/" + value)),因为PDF元数据键在COS层均以/开头。

内容的提问来源于stack exchange,提问作者Chan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:04:58