我需要获取iana.org MediaType而不是application / zip或application / x-tika-msoffice,用于odt,ppt,pptx,xlsx等文件。
如果你看一下mimetypes.xml,那么mimeType元素由iana.org mime-type和“sub-class-of”组成
<mime-type type="application/msword">
<alias type="application/vnd.ms-word"/>
............................
<glob pattern="*.doc"/>
<glob pattern="*.dot"/>
<sub-class-of type="application/x-tika-msoffice"/>
</mime-type>
如何获取iana.org mime-type名称而不是父类型名称?
在测试mime类型检测时,我这样做:
MediaType mediaType = MediaType.parse(tika.detect(inputStream));
String mimeType = mediaType.getSubtype();
测试结果:
FAILED: getsCorrectContentType("application/vnd.ms-excel", docs/xls/en.xls)
java.lang.AssertionError: expected:<application/vnd.ms-excel> but was:<x-tika-msoffice>
FAILED: getsCorrectContentType("vnd.openxmlformats-officedocument.spreadsheetml.sheet", docs/xlsx/en.xlsx)
java.lang.AssertionError: expected:<vnd.openxmlformats-officedocument.spreadsheetml.sheet> but was:<zip>
FAILED: getsCorrectContentType("application/msword", doc/en.doc)
java.lang.AssertionError: expected:<application/msword> but was:<x-tika-msoffice>
FAILED: getsCorrectContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document", docs/docx/en.docx)
java.lang.AssertionError: expected:<application/vnd.openxmlformats-officedocument.wordprocessingml.document> but was:<zip>
FAILED: getsCorrectContentType("vnd.ms-powerpoint", docs/ppt/en.ppt)
java.lang.AssertionError: expected:<vnd.ms-powerpoint> but was:<x-tika-msoffice>
有没有办法从mimetypes.xml获取实际的子类型?而不是x-tika-msoffice或application / zip?
此外,我从未获得application / x-tika-ooxml,但xlsx,docx,pptx文档的应用程序/ zip。
答案 0 :(得分:23)
最初,Tika只支持Mime Magic或文件扩展名(glob)的检测,因为这是Tika之前的大多数mime检测。
由于Mime Magic和Globs在检测容器格式方面存在问题,因此决定在Tika上添加一些新的探测器来处理这些问题。 Container Aware Detectors获取整个文件,打开并处理容器,然后根据内容计算出确切的文件类型。最初,您需要明确地调用它们,但随后它们会被ContainerAwareDetector
包裹起来,您将在一些答案中看到它们。
从那以后,Tika添加了一个服务加载器模式,最初用于Parsers。这允许类在存在时自动加载,通常用于识别哪些类是合适的并使用它们。然后将这种支持扩展到也包括探测器,此时可以移除旧的ContainerAwareDetector
以支持更清洁的东西。
如果您使用的是Tika 1.2或更高版本,并且您希望准确检测所有格式(包括容器格式),则需要执行以下操作:
TikaConfig config = TikaConfig.getDefaultConfig();
Detector detector = config.getDetector();
TikaInputStream stream = TikaInputStream.get(fileOrStream);
Metadata metadata = new Metadata();
metadata.add(Metadata.RESOURCE_NAME_KEY, filenameWithExtension);
MediaType mediaType = detector.detect(stream, metadata);
如果你只用Core Tika jar(tika-core-1.2 -....)来运行它,那么唯一的探测器将是mime magics,你会得到基于魔法的旧式探测器+仅限+ glob。但是,如果您使用Core和Parser Tika jar(以及它们的依赖项)或者Tika App(其中包括核心+解析器+依赖项)自动运行它,那么DefaultDetector将使用所有各种不同的容器检测器来处理您的文件。如果您的文件是基于zip的,那么检测将包括处理zip结构以根据其中的内容识别文件类型。这将为您提供高精度检测,而无需依次调用大量不同的解析器。 DefaultDetector
将使用所有可用的探测器。
答案 1 :(得分:5)
对于其他有类似问题但使用较新的Tika版本的人来说,这应该可以解决问题:
ZipContainerDetector
,因为您可能不再有ContainerAwareDetector
。TikaInputStream
方法提供detect()
,以确保tika可以分析正确的mime类型。我的示例代码如下所示:
public static String getMimeType(final Document p_document)
{
try
{
Metadata metadata = new Metadata();
metadata.add(Metadata.RESOURCE_NAME_KEY, p_document.getDocName());
Detector detector = getDefaultDectector();
LogMF.debug(log, "Trying to detect mime type with detector {0}.", detector);
TikaInputStream inputStream = TikaInputStream.get(p_document.getData(), metadata);
return detector.detect(inputStream, metadata).toString();
}
catch (Throwable t)
{
log.error("Error while determining mime-type of " + p_document);
}
return null;
}
private static Detector getDefaultDectector()
{
if (detector == null)
{
List<Detector> detectors = new ArrayList<>();
// zip compressed container types
detectors.add(new ZipContainerDetector());
// Microsoft stuff
detectors.add(new POIFSContainerDetector());
// mime magic detection as fallback
detectors.add(MimeTypes.getDefaultMimeTypes());
detector = new CompositeDetector(detectors);
}
return detector;
}
请注意,Document
类是我的域模型的一部分。所以你肯定会在那条线上有类似的东西。
我希望有人可以使用它。
答案 2 :(得分:2)
tika-core中的默认字节模式检测规则只能检测所有MS Office文档类型使用的通用OLE2或ZIP格式。您希望使用ContainerAwareDetector进行此类检测。并使用MimeTypes检测器作为其回退检测器。试试这个:
public MediaType getContentType(InputStream is, String fileName) {
MediaType mediaType;
Metadata md = new Metadata();
md.set(Metadata.RESOURCE_NAME_KEY, fileName);
Detector detector = new ContainerAwareDetector(tikaConfig.getMimeRepository());
try {
mediaType = detector.detect(is, md);
} catch (IOException ioe) {
whatever;
}
return mediaType;
}
这样你的测试应该通过
答案 3 :(得分:2)
您可以使用自定义tika配置文件:
MimeTypes mimes=MimeTypesFactory.create(Thread.currentThread()
.getContextClassLoader().getResource("tika-custom-MimeTypes.xml"));
Metadata metadata = new Metadata();
metadata.add(Metadata.RESOURCE_NAME_KEY, file.getName());
tis = TikaInputStream.get(file);
String mimetype = new DefaultDetector(mimes).detect(tis,metadata).toString();
在WEB-INF / classes中,将“tika-custom-MimeTypes.xml”与您的更改放在一起:
就我而言:
<mime-type type="video/mp4">
<magic priority="60">
<match value="ftypmp41" type="string" offset="4"/>
<match value="ftypmp42" type="string" offset="4"/>
<!-- add -->
<match value="ftyp" type="string" offset="4"/>
</magic>
<glob pattern="*.mp4"/>
<glob pattern="*.mp4v"/>
<glob pattern="*.mpg4"/>
<!-- sub-class-of type="video/quicktime" /-->
</mime-type>
<mime-type type="video/quicktime">
<magic priority="50">
<match value="moov" type="string" offset="4"/>
<match value="mdat" type="string" offset="4"/>
<!--remove for videos of screencast -->
<!--match value="ftyp" type="string" offset="4"/-->
</magic>
<glob pattern="*.qt"/>
<glob pattern="*.mov"/>
</mime-type>