使用 Content-Type header 从 eml 文件中提取附件名称

Extracting attachment name from eml file using Content-Type header

我正在使用 Tika-server 来解析一堆 eml 文件。使用 /rmeta 端点时,提取 emls 和附件的内容和元数据工作正常。

正确的附件文件名出现问题。当原始 eml 文件中的附件部分具有以下结构时:

Content-Type: application/pdf; name="filename_a.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="filename_a.pdf"

一切正常:元数据 object 中提取的文件名路径(在 api 响应中)是:

"X-TIKA:embedded_resource_path": "/filename_a.pdf"

但是我的一些电子邮件的 header 结构不正确(Content-Disposition 中缺少文件名)即:

Content-Type: application/pdf; name="filename_a.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;

然后在解析整个 eml 后我得到:

"X-TIKA:embedded_resource_path": "/embedded-1"

我检查了 Tika 的源代码,文件名元在 \org\apache\tika\parser\RecursiveParserWrapper 中定义。class 此处:

 private String getResourceName(Metadata metadata, RecursiveParserWrapper.ParserState state) {
        String objectName = "";
        if (metadata.get("resourceName") != null) {
            objectName = metadata.get("resourceName");
        } else if (metadata.get("embeddedRelationshipId") != null) {
            objectName = metadata.get("embeddedRelationshipId");
        } else {
            objectName = "embedded-" + ++state.unknownCount;
        }

        objectName = FilenameUtils.getName(objectName);
        return objectName;
    }

我试图通过检查元数据 object 中的 Content-Type 键来以某种方式访问​​提到的文件名属性,但它不存在。 (我假设 Tika 评估 Content-type 密钥不仅仅是通过查看适当的 header 因此需要的文件名不存在)

因此我的问题(因为我无法弄清楚)是否有一种方法可以修改 Tika 源代码以在 Content-Type header 中的适当文件名属性时强制从 header 中提取文件名 Content-Disposition header 不见了?

好的,所以我自己解决了。解决方法非常简单明了。

必须扩展 \org\apache\tika\parser\mail\MailContentHandler.class 中的条件之一。在第 129 行,我们有:

if (contentDispositionFileName != null) {
   submd.set("resourceName", contentDispositionFileName);
}

通过扩展额外的 else 块:

if (contentDispositionFileName != null) {
   submd.set("resourceName", contentDispositionFileName);
} else {
    Map<String, String> contentTypeParameters = ((MaximalBodyDescriptor)body).getContentTypeParameters();
    String contentTypeFilename = (String)contentTypeParameters.get("name");
    submd.set("resourceName", contentTypeFilename);
}

我们强制处理程序在内容类型参数中查找额外的文件名 属性。