首页 / 知识

在Java中获取文件的Mime类型

2023-04-14 16:03:00

在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'


    类型文件工具内存

    最新内容

    相关内容

    热门文章

    推荐文章

    标签云

    猜你喜欢