当前位置: 首页 > 工具软件 > James Mime4j > 使用案例 >

java mimetype_在Java中获取文件的Mime类型

仇睿
2023-12-01

我只是想知道大多数人如何从Java中的文件中获取mime类型? 到目前为止,我已经尝试了两个工具:JMimeMagic&Mime-Util。

第一个给了我内存异常,第二个没有正确关闭它的流。 我只是想知道是否有其他人有他们使用和正常工作的方法/库?

rgagnon.com/javadetails/java-0487.html上提供了有关可用库的详细概述

我在这里使用了作为答案发布的类:stackoverflow.com/a/10140531/293280

蒂卡应该是现在的答案。 下面的其他答案说明了与Tika的许多依赖关系,但我没有看到tika-core。

@ javamonkey79当我们使用TIka时,它会隐藏文件并且它不再可用。 String contentType = tika.detect(is)。

在Java 7中,您现在可以使用Files.probeContentType(path)。

这非常有用,因为mime-util网站似乎已关闭,我无法判断库是否正在维护!

这很好用,但我还没有找到一种方法来添加我理解的更多文件类型。例如,ISO映像返回null,.zip存档甚至是ini配置文件也是如此。

@Chris你太棒了! :)

这是一件美丽的事情。

@ james.garriss和它给我的积分比我给过的任何其他答案都多!疯了,是吗? :)

请注意,Files.probeContentType(Path)在多个操作系统上存在错误,并且已经提交了大量错误报告。我在使用ubuntu但在Windows上失败的软件时遇到了问题。似乎在Windows上Files.probeContentType(Path)总是返回null。这不是我的系统,所以我没有检查JRE或Windows版本。它可能是用于Java 7的oracle JRE的Windows 7或8。

我在OS X 10.9上运行,我得到null,.xml,.xhtml和.xhtml文件。我不知道我是在做一些可怕的错误,但这看起来相当可怕。

如果文件没有扩展名,我无法成功运行。

似乎至少在类似* nix的系统上,默认文件类型检测器只返回null,并且必须手动添加一个或多个检测器实现,这看起来并不是太直接。所以至少对于我的用例,这是一个将文件扩展名映射到mime类型的简单方法,这个解决方案不起作用。

这方面的一个主要限制是该文件必须存在于文件系统上。这不适用于流或字节数组等。

甚至更奇怪,我有两个Windows 8.1笔记本电脑,其中一个得到applicationx-zip-compressed而另一个得到null因为在zip文件上调用它。完全不可靠:。因此,鉴于我希望我的应用程序打开文件的编码方案(假设我的应用程序同时采用XML和JSON配置),并且文件简称为配置(没有扩展名),最可靠的方法是什么那个文件的类型,有点作弊和读几个字节?

当我从名称中删除扩展名时,此方法无法返回mime类型。例如,如果名称为test.mp4,我将其更改为"test",方法返回null。同时我将电影扩展名更改为png等,它返回png mime类型

如果文件的扩展名丢失或错误,这将无用。

基于Linux的实现似乎使用Linux / usr / bin / file,这是好的,除非它是一个扩展,它只是相信而不是更深入,这是坏的。如果将XML文件重命名为.json,则会告诉您其JSON。垃圾进垃圾出。除非你确定你的文件数据,否则你真的不想信任这种方法。

@RussBateman unless theres an extension, which it just believes without looking deeper, which is bad. nginx / apache等不只是看扩展吗?

不幸,

mimeType = file.toURL().openConnection().getContentType();

不起作用,因为这种URL的使用会使文件被锁定,因此,例如,它是不可删除的。

但是,你有这个:

mimeType= URLConnection.guessContentTypeFromName(file.getName());

以及以下内容,其优点是不仅仅使用文件扩展名,还可以查看内容

InputStream is = new BufferedInputStream(new FileInputStream(file));

mimeType = URLConnection.guessContentTypeFromStream(is);

//...close stream

但是,正如上面的评论所暗示的那样,内置的mime类型表非常有限,不包括例如MSWord和PDF。因此,如果你想要概括,你需要超越内置库,使用例如Mime-Util(这是一个很棒的库,同时使用文件扩展名和内容)。

完美的解决方案 - 帮助了我很多!将FileInputStream包装到BufferedInputStream是至关重要的部分 - 否则guessContentTypeFromStream返回null(传递InputStream实例应该支持标记)

Howerver,URLConnection具有一组非常有限的内容类型,可以识别。例如,它无法检测applicationpdf。

@kpentchev它为我检测pdf。但它没有检测办公室文件,例如* .DOC

它只会让它锁定,因为你没有办法将它关闭。断开URLConnection将解锁它。

guessContentTypeFromStream和guessContentTypeFromName都不识别例如MP4

guessContentTypeFromName()使用默认的$JAVA_HOMElibcontent-types.properties文件。您可以通过更改系统属性System.setProperty("content.types.user.table","libpathtoyourpropertyfile");来添加自己的扩展文件

它没有检测.js,.css文件。还有其他方法来检测这些文件吗?

任何链接到Mime-Util ???我在github中找到了项目但是不包含任何描述:(

guessContentTypeFromName在多线程中使用此synchronized FileNameMap getFileNameMap祝你好运

JAF API是JDK 6的一部分。查看javax.activation包。

最有趣的类是javax.activation.MimeType - 一个实际的MIME类型持有者 - 和javax.activation.MimetypesFileTypeMap - 类,其实例可以将MIME类型解析为文件的String:

String fileName ="/path/to/file";

MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();

// only by file name

String mimeType = mimeTypesMap.getContentType(fileName);

// or by actual File instance

File file = new File(fileName);

mimeType = mimeTypesMap.getContentType(file);

不幸的是,由于getContentType(File)的javadoc状态:返回文件对象的MIME类型。此类中的实现调用getContentType(f.getName())。

请记住,您可以使用META-INF / mime.types文件扩展此功能,因此如果您被迫使用Java 6,它是完美的.docs.oracle.com / java / 5 / api / javax / activation /

您可以跳过MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(file)创建新对象

感谢您的回答。它成功地为我工作。

但它仍然只返回基于文件名的内容类型。这对用户上传的文件尤其危险。

使用Apache Tika,您只需要三行代码:

File file = new File("/path/to/file");

Tika tika = new Tika();

System.out.println(tika.detect(file));

如果你有一个groovy控制台,只需粘贴并运行此代码即可:

@Grab('org.apache.tika:tika-core:1.14')

import org.apache.tika.Tika;

def tika = new Tika()

def file = new File("/path/to/file")

println tika.detect(file)

请记住,它的API很丰富,它可以解析"任何东西"。截至tika-core 1.14,你有:

String  detect(byte[] prefix)

String  detect(byte[] prefix, String name)

String  detect(File file)

String  detect(InputStream stream)

String  detect(InputStream stream, Metadata metadata)

String  detect(InputStream stream, String name)

String  detect(Path path)

String  detect(String name)

String  detect(URL url)

有关更多信息,请参阅apidocs。

它对csv不起作用。WTF?stackoverflow.com/questions/46960231/

关于Tika的一件坏事,很多依赖性臃肿。 它增加了我的罐子大小54MB!

@helmyTika 1.17是独立的,只有648 KB大。

...或仅new Tika().detect(file.toPath())用于基于文件扩展名的检测,而不是基于文件内容进行检测

@ Lu55文档说仍然使用文档内容。 我认为你的意思是new Tika().detect(file.getPath()),它只使用文件扩展名

Apache Tika在tika-core中提供基于流前缀中的魔术标记的mime类型检测。 tika-core不会获取其他依赖项,这使得它与当前未维护的Mime类型检测实用程序一样轻量级。

简单的代码示例(Java 7),使用变量theInputStream和theFileName

try (InputStream is = theInputStream;

BufferedInputStream bis = new BufferedInputStream(is);) {

AutoDetectParser parser = new AutoDetectParser();

Detector detector = parser.getDetector();

Metadata md = new Metadata();

md.add(Metadata.RESOURCE_NAME_KEY, theFileName);

MediaType mediaType = detector.detect(bis, md);

return mediaType.toString();

}

请注意,MediaType.detect(...)不能直接使用(TIKA-1120)。 https://tika.apache.org/0.10/detection.html提供了更多提示。

+1此外Metadata.RESOURCE_NAME_KEY可以省略(如果你没有或不能依赖原始名称),但在这种情况下,你会在某些情况下得到错误的结果(例如办公室文件)。

如果文件名没有扩展名,那么检测XLSX会有一些问题......但这个解决方案简单而优雅。

如果您是Android开发人员,则可以使用实用程序类android.webkit.MimeTypeMap将MIME类型映射到文件扩展名,反之亦然。

以下代码段可能会对您有所帮助。

private static String getMimeType(String fileUrl) {

String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);

return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);

}

如果尝试使用本地文件路径(例如"/sdcard/path/to/video.extension"),这也有效。问题是如果本地文件在其路径中包含空格,则它始终返回null

来自roseindia:

FileNameMap fileNameMap = URLConnection.getFileNameMap();

String mimeType = fileNameMap.getContentTypeFor("alert.gif");

无论谁投票给答案,请添加评论,以便我(和其他人)可以学习发布更好的答案。

我没有投票给你,但getFileNameMap不适用于许多基本文件类型,例如bmp。 URLConnection.guessContentTypeFromName也返回相同的内容

功能很不完整。从Java 7开始,html,pdf和jpeg扩展返回正确的mime类型,但js和css返回null!

我用webm测试过,它返回null。

如果您遇到java 5-6那么这个实用程序类来自servoy开源产品。

你只需要这个功能

public static String getContentType(byte[] data, String name)

它探测内容的第一个字节,并根据该内容而不是文件扩展名返回内容类型。

这就是我所寻找的,工作完美。

为我需要的简单,流行和少数文件类型工作:)

I was just wondering how most people fetch a mime type from a file in Java?

我发布了我的SimpleMagic Java包,它允许从文件和字节数组中确定内容类型(mime类型)。它旨在读取和运行Unix文件(1)命令魔术文件,这些文件是大多数Unix操作系统配置的一部分。

我尝试过Apache Tika,但是它有很多依赖项,URLConnection不使用文件的字节,而MimetypesFileTypeMap也只是查看文件名。

使用SimpleMagic,您可以执行以下操作:

// create a magic utility using the internal magic file

ContentInfoUtil util = new ContentInfoUtil();

// if you want to use a different config file(s), you can load them by hand:

// ContentInfoUtil util = new ContentInfoUtil("/etc/magic");

...

ContentInfo info = util.findMatch("/tmp/upload.tmp");

// or

ContentInfo info = util.findMatch(inputStream);

// or

ContentInfo info = util.findMatch(contentByteArray);

// null if no match

if (info != null) {

String mimeType = info.getMimeType();

}

在多个图像文件上测试它。所有扩展都已重命名。你真棒的图书馆正确处理了它。当然它的光也是:)。

是的,这很好用。对于那些需要在Android中使用此解决方案的人,您只需在build.gradle文件中包含以下内容:compile(com.j256.simplemagic:simplemagic:1.10)

这是一个很好的解决方案!谢谢!

用我的5美分筹码:

TL,DR

我使用MimetypesFileTypeMap并将任何不存在的mime添加到mime.types文件中,我特别需要它。

现在,长读:

首先,MIME类型列表很大,请参见:https://www.iana.org/assignments/media-types/media-types.xhtml

我想首先使用JDK提供的标准工具,如果这不起作用,我会去寻找其他东西。

从文件扩展名确定文件类型

从1.6开始,Java有MimetypesFileTypeMap,如上面的一个答案中所指出的,它是确定mime类型的最简单方法:

new MimetypesFileTypeMap().getContentType( fileName );

在它的vanilla实现中,这没有太大作用(即它适用于.html但不适用于.png)。但是,添加您可能需要的任何内容类型非常简单:

在项目的META-INF文件夹中创建名为"mime.types"的文件

为你需要的每个mime类型添加一行,默认实现不提供(有数百种mime类型,列表随着时间的推移而增长)。

png和js文件的示例条目是:

image/png png PNG

application/javascript js

有关mime.types文件格式,请在此处查看更多详细信息:https://docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.html

从文件内容确定文件类型

从1.7开始,Java有java.nio.file.spi.FileTypeDetector,它定义了一个标准API,用于以特定于实现的方式确定文件类型。

要获取文件的mime类型,您只需使用Files并在代码中执行此操作:

Files.probeContentType(Paths.get("either file name or full path goes here"));

API定义提供了支持从文件名或文件内容(魔术字节)确定文件mime类型的工具。这就是为什么probeContentType()方法抛出IOException,以防此API的实现使用提供给它的Path来实际尝试打开与之关联的文件。

同样,vanilla的实现(JDK附带的实现)还有很多不足之处。

在遥远的银河系中的一些理想世界中,所有这些试图解决这个文件到mime类型问题的库只会实现java.nio.file.spi.FileTypeDetector,你会放入首选的实现库的jar将文件放入您的类路径中,就可以了。

在现实世界中,你需要TL,DR部分,你应该找到其名称旁边有大多数星星的图书馆并使用它。对于这种特殊情况,我不需要一个(还有))。

我尝试了几种方法,包括@Joshua Fox所说的第一种方法。但有些人不认识频繁的mimetypes,比如PDF文件,而其他人不能用假文件来信任(我尝试使用扩展名改为TIF的RAR文件)。我发现的解决方案,正如@Joshua Fox以肤浅的方式所说,是使用MimeUtil2,如下所示:

MimeUtil2 mimeUtil = new MimeUtil2();

mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");

String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();

我没有成功使用MimeUtil2 - 几乎所有东西都以应用程序/八位字节流的形式返回。在使用`MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector")初始化之后,我使用MimeUtil.getMimeTypes()取得了更大的成功; MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.ExtensionMimeDetector"); MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.OpendesktopMimeDetector"); `

感谢您的工作解决方案。 mime-util的文档对于如何实例化实用程序类不是很清楚。最后启动并运行,但用实际的类替换了classname字符串。 MimeUtil.registerMimeDetector(ExtensionMimeDetector.class.getName()); String mimeType = MimeUtil.getMostSpecificMimeType(MimeUtil.getMimeTypes(filename))。toString();

最好对文件上传使用两层验证。

首先,您可以检查mimeType并验证它。

其次,您应该将文件的前4个字节转换为十六进制,然后将其与幻数进行比较。那么它将是一种检查文件验证的真正安全的方法。

在Spring MultipartFile文件中;

org.springframework.web.multipart.MultipartFile

file.getContentType();

为什么春天???关于java的问题。

这是我发现这样做的最简单方法:

byte[] byteArray = ...

InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));

String mimeType = URLConnection.guessContentTypeFromStream(is);

我用下面的代码做了。

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.HttpURLConnection;

import java.net.URL;

public class MimeFileType {

public static void main(String args[]){

try{

URL url = new URL ("https://www.url.com.pdf");

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

connection.setRequestMethod("GET");

connection.setDoOutput(true);

InputStream content = (InputStream)connection.getInputStream();

connection.getHeaderField("Content-Type");

System.out.println("Content-Type"+ connection.getHeaderField("Content-Type"));

BufferedReader in = new BufferedReader (new InputStreamReader(content));

}catch (Exception e){

}

}

}

在尝试了各种其他库之后,我决定使用mime-util。

eu.medsea.mimeutil

mime-util

2.1.3

File file = new File("D:/test.tif");

MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");

Collection< ? > mimeTypes = MimeUtil.getMimeTypes(file);

System.out.println(mimeTypes);

public String getFileContentType(String fileName) {

String fileType ="Undetermined";

final File file = new File(fileName);

try

{

fileType = Files.probeContentType(file.toPath());

}

catch (IOException ioException)

{

System.out.println(

"ERROR: Unable to determine file type for" + fileName

+" due to exception" + ioException);

}

return fileType;

}

自JDK 1.7版以来,这个方法Files.probeContentType(String)可用,对我来说非常有用。

谢谢,只有我不明白为什么有些用户做了投票)))

根本没有,也许他们有早期版本的JDK :)))

你只需要一行即可:MimetypesFileTypeMap()。getContentType(new File("filename.ext"))。查看完整的测试代码(Java 7):

import java.io.File;

import javax.activation.MimetypesFileTypeMap;

public class MimeTest {

public static void main(String a[]){

System.out.println(new MimetypesFileTypeMap().getContentType(

new File("/path/filename.txt")));

}

}

此代码生成以下输出:text / plain

File file = new File(PropertiesReader.FILE_PATH);

MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();

String mimeType = fileTypeMap.getContentType(file);

URLConnection uconnection = file.toURL().openConnection();

mimeType = uconnection.getContentType();

@Shree你的链接不起作用。

虽然此代码可以解决问题,但包括解释确实有助于提高帖子的质量。

如果你在linux OS上工作,有一个命令行file --mimetype:

String mimetype(file){

//1. run cmd

Object cmd=Runtime.getRuntime().exec("file --mime-type"+file);

//2 get output of cmd , then

//3. parse mimetype

if(output){return output.split(":")[1].trim(); }

return"";

}

然后

mimetype("/home/nyapp.war") //  'application/zip'

mimetype("/var/www/ggg/au.mp3") //  'audio/mp3'

这可行,但IMO是一种不好的做法,因为它将您的代码绑定到特定的操作系统,并要求外部实用程序出现在运行它的系统上。别误会我的意思;它是一个完全有效的解决方案,但打破了可移植性 - 这是首先使用Java的主要原因之一......

@ToVine:为了记录,我会恭敬地不同意。并非每个Java程序都是可移植的。让上下文和程序员做出决定。 en.wikipedia.org/wiki/Java_Native_Interface

 类似资料: