在Java中获取文件的Mime类型

在Java中获取文件的Mime类型

Getting A File's Mime Type In Java

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

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


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


不幸,

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

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

但是,你有这个:

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

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

1
2
3
InputStream is = new BufferedInputStream(new FileInputStream(file));
mimeType = URLConnection.guessContentTypeFromStream(is);
 //...close stream

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


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

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

1
2
3
4
5
6
7
8
9
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);

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

1
2
3
File file = new File("/path/to/file");
Tika tika = new Tika();
System.out.println(tika.detect(file));

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

1
2
3
4
5
6
@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,你有:

1
2
3
4
5
6
7
8
9
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。


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

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

1
2
3
4
5
6
7
8
9
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提供了更多提示。


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

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

1
2
3
4
private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}

来自roseindia:

1
2
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.webp");

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

你只需要这个功能

1
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,您可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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();
}


用我的5美分筹码:

TL,DR

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

现在,长读:

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

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

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

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

1
new MimetypesFileTypeMap().getContentType( fileName );

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

  • 在项目的META-INF文件夹中创建名为"mime.types"的文件
  • 为你需要的每个mime类型添加一行,默认实现不提供(有数百种mime类型,列表随着时间的推移而增长)。
  • png和js文件的示例条目是:

    1
    2
    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并在代码中执行此操作:

    1
    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,如下所示:

    1
    2
    3
    MimeUtil2 mimeUtil = new MimeUtil2();
    mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
    String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();

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

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

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


    在Spring MultipartFile文件中;

    org.springframework.web.multipart.MultipartFile

    file.getContentType();


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

    1
    2
    3
    byte[] byteArray = ...
    InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));
    String mimeType = URLConnection.guessContentTypeFromStream(is);


    我用下面的代码做了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    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。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <groupId>eu.medsea.mimeutil</groupId>
          mime-util</artifactId>
          <version>2.1.3</version>
    </dependency>

    File file = new File("D:/test.tif");
    MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
    Collection< ? > mimeTypes = MimeUtil.getMimeTypes(file);
    System.out.println(mimeTypes);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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;
    }

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

    1
    2
    3
    4
    5
    6
    7
    8
    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


    1
    2
    3
    4
    5
    File file = new File(PropertiesReader.FILE_PATH);
    MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
    String mimeType = fileTypeMap.getContentType(file);
    URLConnection uconnection = file.toURL().openConnection();
    mimeType = uconnection.getContentType();


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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"";
    }

    然后

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

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


    推荐阅读

      linux命令添加文件?

      linux命令添加文件?,工作,简介,数据,系统,文件,命令,操作,文件名,内容,终端,l

      查看linux类型命令?

      查看linux类型命令?,系统,信息,命令,状态,数据,数字,情况,地址,类型,文件,lin

      linux文件中剪切命令?

      linux文件中剪切命令?,位置,系统,工作,命令,发行,连续,标准,终端,文件,目录,l

      linux存储文件命令?

      linux存储文件命令?,系统,地址,工作,命令,软件,电脑,标准,底部,信息,文件,lin

      linux命令移除文件夹?

      linux命令移除文件夹?,命令,文件夹,通用,不了,数据,名称,档案,系统,文件,目

      开发linux命令工具?

      开发linux命令工具?,系统,工具,环境,状态,平台,设计,数据,电脑,中小企业,标

      在linux文件后加命令?

      在linux文件后加命令?,系统,工作,命令,工具,电脑,基础,管理,情况,第一,简介,L

      linux命令删除文件夹?

      linux命令删除文件夹?,系统,名称,环境,文件夹,不了,命令,文件,数据,档案,目

      linux命令看文件编码?

      linux命令看文件编码?,状态,系统,文件,工具,名称,数据,命令,格式,汉字,以下,L

      linux编辑文件的命令?

      linux编辑文件的命令?,系统,地址,工作,状态,命令,电脑,信息,管理,目录,终端,l

      linux命令行关掉文件?

      linux命令行关掉文件?,地址,状态,工作,系统,信息,命令,名字,电脑,编辑,文件,l

      linux分隔文件命令?

      linux分隔文件命令?,系统,信息,文件,命令,位置,指令,文件夹,目录,前缀,方法,l

      linux改文件权限命令?

      linux改文件权限命令?,系统,工具,档案,权限,文件,信息,命令,目录,选项,用户,

      linux命令联想工具?

      linux命令联想工具?,地址,工作,系统,工具,状态,标准,信息,命令,目录,左下角,L

      linux命令交换文件名?

      linux命令交换文件名?,命令,文件,数据,名称,工具,地址,软件,系统,基础知识,

      查看linux库类型命令?

      查看linux库类型命令?,系统,工作,信息,状态,电脑,命令,工具,代码,地址,发行,

      linux文件夹转移命令?

      linux文件夹转移命令?,系统,文件,命令,位置,材料,信息,工具,电脑,目录,源文

      linux转移文件命令?

      linux转移文件命令?,文件,命令,密码,电脑,位置,名称,信息,系统,目录,目标,lin

      linux下替换文件命令?

      linux下替换文件命令?,文件,一致,评论,名称,标的,资料,工作,命令,字符串,内