370

如何使用 Java 从文件中获取媒体类型(MIME 类型)?到目前为止,我已经尝试过 JMimeMagic 和 Mime-Util。第一个给了我内存异常,第二个没有正确关闭它的流。

您将如何探测文件以确定其实际类型(不仅仅是基于扩展名)?

4

28 回答 28

343

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

于 2012-01-23T14:49:23.020 回答
233

很遗憾,

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(这是一个很棒的库,同时使用文件扩展名和内容)。

于 2009-05-11T12:21:22.840 回答
61

使用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

于 2017-02-14T15:24:20.833 回答
51

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);
于 2009-12-14T17:02:50.520 回答
36

Apache Tikatika-core中提供了基于流前缀中的魔法标记的 mime 类型检测。tika-core不获取其他依赖项,这使其与当前未维护的Mime Type Detection Utility一样轻量级。

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

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/1.24/detection.html提供了更多提示。

于 2013-05-18T16:14:54.453 回答
26

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

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

private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
于 2012-12-15T06:23:39.707 回答
19

来自玫瑰印地亚

FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");
于 2011-08-01T13:34:59.857 回答
17

如果你被 java 5-6 卡住了,那么这个来自servoy开源产品的实用程序类。

你只需要这个功能

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

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

于 2013-09-05T15:20:30.407 回答
14

我只是想知道大多数人如何从 Java 文件中获取 mime 类型?

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

我尝试了 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();
}
于 2013-06-25T16:07:42.463 回答
7

用我的 5 美分筹码:

总长,博士

我使用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 );

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

  1. 在项目的 META-INF 文件夹中创建名为“mime.types”的文件
  2. 为您需要的每种 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 来实际尝试打开与其关联的文件。

同样,这个(JDK 附带的)的普通实现还有很多不足之处

在遥远星系中的某个理想世界中,所有这些试图解决文件到mime-type问题的库都将简单地实现java.nio.file.spi.FileTypeDetector,您将放入首选实现库的 jar文件到你的类路径中,就是这样。

在现实世界中,您需要 TL、DR 部分,您应该找到名称旁边有最多星号的库并使用它。对于这种特殊情况,我不需要一个(还;))。

于 2017-09-25T14:03:28.770 回答
4

我尝试了几种方法来做到这一点,包括@Joshua Fox 所说的第一种方法。但是有些人无法识别常见的模仿类型,例如 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();
于 2012-09-21T17:03:51.317 回答
4

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

byte[] byteArray = ...
InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));
String mimeType = URLConnection.guessContentTypeFromStream(is);
于 2017-02-23T14:16:41.323 回答
4

阿帕奇蒂卡。

<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.24</version>
</dependency>

和两行代码。

Tika tika=new Tika();
tika.detect(inputStream);

下面的截图

在此处输入图像描述

于 2020-05-10T18:14:47.530 回答
4

简单和最佳选项从文件位置检索内容 mime 类型。

使用这个进口

import java.nio.file.Files;
import java.nio.file.Path;

代码

String type = Files.probeContentType(Path.of(imagePath));
于 2020-12-29T18:52:30.053 回答
3

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

首先,您可以检查 mimeType 并对其进行验证。

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

于 2014-08-19T09:26:03.283 回答
3

您只需一行即可完成: 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

于 2018-02-03T01:44:33.573 回答
3

如果您正在使用 Servlet,并且您可以使用 Servlet 上下文,则可以使用:

getServletContext().getMimeType( fileName );
于 2019-11-11T06:13:48.927 回答
3

我找不到任何可以检查video/mp4MIME 类型的内容,所以我制定了自己的解决方案。我碰巧观察到 Wikipedia 是错误的,并且00 00 00 18 66 74 79 70 69 73 6F 6D文件签名不正确。第四个字节(18)和所有70(排除)在其他有效mp4文件中发生了很大变化之后。

此代码本质上是代码的复制/粘贴,URLConnection.guessContentTypeFromStream但针对video/mp4.

BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(content));
String mimeType = URLConnection.guessContentTypeFromStream(bis);

// Goes full barbaric and processes the bytes manually
if (mimeType == null){
    // These ints converted in hex ar:
    // 00 00 00 18 66 74 79 70 69 73 6F 6D
    // which are the file signature (magic bytes) for .mp4 files
    // from https://www.wikiwand.com/en/List_of_file_signatures
    // just ctrl+f "mp4"
    int[] mp4_sig = {0, 0, 0, 24, 102, 116, 121, 112};

    bis.reset();
    bis.mark(16);
    int[] firstBytes = new int[8];
    for (int i = 0; i < 8; i++) {
        firstBytes[i] = bis.read();
    }
    // This byte doesn't matter for the file signature and changes
    mp4_sig[3] = content[3];

    bis.reset();
    if (Arrays.equals(firstBytes, mp4_sig)){
        mimeType = "video/mp4";
    }
}

针对 10 个不同的.mp4文件成功测试。

编辑:这是一个有用的链接(如果它仍然在线),您可以在其中找到多种类型的示例。我不拥有这些视频,也不知道谁拥有,但它们对于测试上述代码很有用。

于 2020-11-03T21:44:13.460 回答
2

实际上,Apache Tika 检测器 Tika.detect(File)是最好的选择,并且比Files.probeContentType(path).

检查这个包含示例和代码示例的快速参考。

于 2021-10-27T11:02:01.113 回答
1

在 Spring MultipartFile文件中;

org.springframework.web.multipart.MultipartFile

file.getContentType();

于 2016-04-26T11:33:13.907 回答
1

检测文件的媒体类型1的解决方案包含以下部分:

如果您复制代码,请记住给予信用。

StreamMediaType.java

在下面的代码-1中,意味着跳过比较该索引处的字节;a-2表示文件类型签名的结尾。这会检测二进制格式,主要是图像和一些纯文本格式变体(HTML、SVG、XML)。该代码最多使用数据源标头中的前 11 个“魔术”字节。欢迎进行缩短逻辑的优化和改进。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.Map;

import static com.keenwrite.io.MediaType.*;
import static java.lang.System.arraycopy;

public class StreamMediaType {
  private static final int FORMAT_LENGTH = 11;
  private static final int END_OF_DATA = -2;

  private static final Map<int[], MediaType> FORMAT = new LinkedHashMap<>();

  static {
    //@formatter:off
    FORMAT.put( ints( 0x3C, 0x73, 0x76, 0x67, 0x20 ), IMAGE_SVG_XML );
    FORMAT.put( ints( 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ), IMAGE_PNG );
    FORMAT.put( ints( 0xFF, 0xD8, 0xFF, 0xE0 ), IMAGE_JPEG );
    FORMAT.put( ints( 0xFF, 0xD8, 0xFF, 0xEE ), IMAGE_JPEG );
    FORMAT.put( ints( 0xFF, 0xD8, 0xFF, 0xE1, -1, -1, 0x45, 0x78, 0x69, 0x66, 0x00 ), IMAGE_JPEG );
    FORMAT.put( ints( 0x49, 0x49, 0x2A, 0x00 ), IMAGE_TIFF );
    FORMAT.put( ints( 0x4D, 0x4D, 0x00, 0x2A ), IMAGE_TIFF );
    FORMAT.put( ints( 0x47, 0x49, 0x46, 0x38 ), IMAGE_GIF );
    FORMAT.put( ints( 0x8A, 0x4D, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ), VIDEO_MNG );
    FORMAT.put( ints( 0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E ), APP_PDF );
    FORMAT.put( ints( 0x38, 0x42, 0x50, 0x53, 0x00, 0x01 ), IMAGE_PHOTOSHOP );
    FORMAT.put( ints( 0x25, 0x21, 0x50, 0x53, 0x2D, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x2D ), APP_EPS );
    FORMAT.put( ints( 0x25, 0x21, 0x50, 0x53 ), APP_PS );
    FORMAT.put( ints( 0xFF, 0xFB, 0x30 ), AUDIO_MP3 );
    FORMAT.put( ints( 0x49, 0x44, 0x33 ), AUDIO_MP3 );
    FORMAT.put( ints( 0x3C, 0x21 ), TEXT_HTML );
    FORMAT.put( ints( 0x3C, 0x68, 0x74, 0x6D, 0x6C ), TEXT_HTML );
    FORMAT.put( ints( 0x3C, 0x68, 0x65, 0x61, 0x64 ), TEXT_HTML );
    FORMAT.put( ints( 0x3C, 0x62, 0x6F, 0x64, 0x79 ), TEXT_HTML );
    FORMAT.put( ints( 0x3C, 0x48, 0x54, 0x4D, 0x4C ), TEXT_HTML );
    FORMAT.put( ints( 0x3C, 0x48, 0x45, 0x41, 0x44 ), TEXT_HTML );
    FORMAT.put( ints( 0x3C, 0x42, 0x4F, 0x44, 0x59 ), TEXT_HTML );
    FORMAT.put( ints( 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20 ), TEXT_XML );
    FORMAT.put( ints( 0xFE, 0xFF, 0x00, 0x3C, 0x00, 0x3f, 0x00, 0x78 ), TEXT_XML );
    FORMAT.put( ints( 0xFF, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0x78, 0x00 ), TEXT_XML );
    FORMAT.put( ints( 0x42, 0x4D ), IMAGE_BMP );
    FORMAT.put( ints( 0x23, 0x64, 0x65, 0x66 ), IMAGE_X_BITMAP );
    FORMAT.put( ints( 0x21, 0x20, 0x58, 0x50, 0x4D, 0x32 ), IMAGE_X_PIXMAP );
    FORMAT.put( ints( 0x2E, 0x73, 0x6E, 0x64 ), AUDIO_BASIC );
    FORMAT.put( ints( 0x64, 0x6E, 0x73, 0x2E ), AUDIO_BASIC );
    FORMAT.put( ints( 0x52, 0x49, 0x46, 0x46 ), AUDIO_WAV );
    FORMAT.put( ints( 0x50, 0x4B ), APP_ZIP );
    FORMAT.put( ints( 0x41, 0x43, -1, -1, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00 ), APP_ACAD );
    FORMAT.put( ints( 0xCA, 0xFE, 0xBA, 0xBE ), APP_JAVA );
    FORMAT.put( ints( 0xAC, 0xED ), APP_JAVA_OBJECT );
    //@formatter:on
  }

  private StreamMediaType() {
  }

  public static MediaType getMediaType( final Path path ) throws IOException {
    return getMediaType( path.toFile() );
  }

  public static MediaType getMediaType( final java.io.File file )
    throws IOException {
    try( final var fis = new FileInputStream( file ) ) {
      return getMediaType( fis );
    }
  }

  public static MediaType getMediaType( final InputStream is )
    throws IOException {
    final var input = new byte[ FORMAT_LENGTH ];
    final var count = is.read( input, 0, FORMAT_LENGTH );

    if( count > 1 ) {
      final var available = new byte[ count ];
      arraycopy( input, 0, available, 0, count );
      return getMediaType( available );
    }

    return UNDEFINED;
  }

  public static MediaType getMediaType( final byte[] data ) {
    assert data != null;

    final var source = new int[]{
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

    for( int i = 0; i < data.length; i++ ) {
      source[ i ] = data[ i ] & 0xFF;
    }

    for( final var key : FORMAT.keySet() ) {
      int i = -1;
      boolean matches = true;

      while( ++i < FORMAT_LENGTH && key[ i ] != END_OF_DATA && matches ) {
        matches = key[ i ] == source[ i ] || key[ i ] == -1;
      }

      if( matches ) {
        return FORMAT.get( key );
      }
    }

    return UNDEFINED;
  }

  private static int[] ints( final int... data ) {
    final var magic = new int[ FORMAT_LENGTH ];
    int i = -1;
    while( ++i < data.length ) {
      magic[ i ] = data[ i ];
    }

    while( i < FORMAT_LENGTH ) {
      magic[ i++ ] = END_OF_DATA;
    }

    return magic;
  }
}

媒体类型.java

根据IANA 媒体类型列表定义文件格式。请注意,文件扩展名映射在MediaTypeExtension. 它的getExtension功能依赖于 Apache 的 FilenameUtils 类。

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;

import static MediaType.TypeName.*;
import static MediaTypeExtension.getMediaType;
import static org.apache.commons.io.FilenameUtils.getExtension;

public enum MediaType {
  APP_ACAD( APPLICATION, "acad" ),
  APP_JAVA_OBJECT( APPLICATION, "x-java-serialized-object" ),
  APP_JAVA( APPLICATION, "java" ),
  APP_PS( APPLICATION, "postscript" ),
  APP_EPS( APPLICATION, "eps" ),
  APP_PDF( APPLICATION, "pdf" ),
  APP_ZIP( APPLICATION, "zip" ),
  FONT_OTF( "otf" ),
  FONT_TTF( "ttf" ),
  IMAGE_APNG( "apng" ),
  IMAGE_ACES( "aces" ),
  IMAGE_AVCI( "avci" ),
  IMAGE_AVCS( "avcs" ),
  IMAGE_BMP( "bmp" ),
  IMAGE_CGM( "cgm" ),
  IMAGE_DICOM_RLE( "dicom_rle" ),
  IMAGE_EMF( "emf" ),
  IMAGE_EXAMPLE( "example" ),
  IMAGE_FITS( "fits" ),
  IMAGE_G3FAX( "g3fax" ),
  IMAGE_GIF( "gif" ),
  IMAGE_HEIC( "heic" ),
  IMAGE_HEIF( "heif" ),
  IMAGE_HEJ2K( "hej2k" ),
  IMAGE_HSJ2( "hsj2" ),
  IMAGE_X_ICON( "x-icon" ),
  IMAGE_JLS( "jls" ),
  IMAGE_JP2( "jp2" ),
  IMAGE_JPEG( "jpeg" ),
  IMAGE_JPH( "jph" ),
  IMAGE_JPHC( "jphc" ),
  IMAGE_JPM( "jpm" ),
  IMAGE_JPX( "jpx" ),
  IMAGE_JXR( "jxr" ),
  IMAGE_JXRA( "jxrA" ),
  IMAGE_JXRS( "jxrS" ),
  IMAGE_JXS( "jxs" ),
  IMAGE_JXSC( "jxsc" ),
  IMAGE_JXSI( "jxsi" ),
  IMAGE_JXSS( "jxss" ),
  IMAGE_KTX( "ktx" ),
  IMAGE_KTX2( "ktx2" ),
  IMAGE_NAPLPS( "naplps" ),
  IMAGE_PNG( "png" ),
  IMAGE_PHOTOSHOP( "photoshop" ),
  IMAGE_SVG_XML( "svg+xml" ),
  IMAGE_T38( "t38" ),
  IMAGE_TIFF( "tiff" ),
  IMAGE_WEBP( "webp" ),
  IMAGE_WMF( "wmf" ),
  IMAGE_X_BITMAP( "x-xbitmap" ),
  IMAGE_X_PIXMAP( "x-xpixmap" ),
  AUDIO_BASIC( AUDIO, "basic" ),
  AUDIO_MP3( AUDIO, "mp3" ),
  AUDIO_WAV( AUDIO, "x-wav" ),
  VIDEO_MNG( VIDEO, "x-mng" ),
  TEXT_HTML( TEXT, "html" ),
  TEXT_MARKDOWN( TEXT, "markdown" ),
  TEXT_PLAIN( TEXT, "plain" ),
  TEXT_XHTML( TEXT, "xhtml+xml" ),
  TEXT_XML( TEXT, "xml" ),
  TEXT_YAML( TEXT, "yaml" ),

  /*
   * When all other lights go out.
   */
  UNDEFINED( TypeName.UNDEFINED, "undefined" );

  public enum TypeName {
    APPLICATION,
    AUDIO,
    IMAGE,
    TEXT,
    UNDEFINED,
    VIDEO
  }

  private final String mMediaType;
  private final TypeName mTypeName;
  private final String mSubtype;

  MediaType( final String subtype ) {
    this( IMAGE, subtype );
  }

  MediaType( final TypeName typeName, final String subtype ) {
    mTypeName = typeName;
    mSubtype = subtype;
    mMediaType = typeName.toString().toLowerCase() + '/' + subtype;
  }

  public static MediaType valueFrom( final File file ) {
    assert file != null;
    return fromFilename( file.getName() );
  }

  public static MediaType fromFilename( final String filename ) {
    assert filename != null;
    return getMediaType( getExtension( filename ) );
  }

  public static MediaType valueFrom( final Path path ) {
    assert path != null;
    return valueFrom( path.toFile() );
  }

  public static MediaType valueFrom( String contentType ) {
    if( contentType == null || contentType.isBlank() ) {
      return UNDEFINED;
    }

    var i = contentType.indexOf( ';' );
    contentType = contentType.substring(
      0, i == -1 ? contentType.length() : i );

    i = contentType.indexOf( '/' );
    i = i == -1 ? contentType.length() : i;
    final var type = contentType.substring( 0, i );
    final var subtype = contentType.substring( i + 1 );

    return valueFrom( type, subtype );
  }

  public static MediaType valueFrom(
    final String type, final String subtype ) {
    assert type != null;
    assert subtype != null;

    for( final var mediaType : values() ) {
      if( mediaType.equals( type, subtype ) ) {
        return mediaType;
      }
    }

    return UNDEFINED;
  }

  public boolean equals( final String type, final String subtype ) {
    assert type != null;
    assert subtype != null;

    return mTypeName.name().equalsIgnoreCase( type ) &&
      mSubtype.equalsIgnoreCase( subtype );
  }

  public boolean isType( final TypeName typeName ) {
    return mTypeName == typeName;
  }

  public String getSubtype() {
    return mSubtype;
  }
   
  @Override
  public String toString() {
    return mMediaType;
  }
}

MediaTypeExtension.java

最后一块拼图是MediaTypes 到它们已知和常见/流行的文件扩展名的映射。这允许基于文件扩展名的双向查找。

import static MediaType.*;
import static java.util.List.of;

public enum MediaTypeExtension {
  MEDIA_APP_ACAD( APP_ACAD, of( "dwg" ) ),
  MEDIA_APP_PDF( APP_PDF ),
  MEDIA_APP_PS( APP_PS, of( "ps" ) ),
  MEDIA_APP_EPS( APP_EPS ),
  MEDIA_APP_ZIP( APP_ZIP ),

  MEDIA_AUDIO_MP3( AUDIO_MP3 ),
  MEDIA_AUDIO_BASIC( AUDIO_BASIC, of( "au" ) ),
  MEDIA_AUDIO_WAV( AUDIO_WAV, of( "wav" ) ),

  MEDIA_FONT_OTF( FONT_OTF ),
  MEDIA_FONT_TTF( FONT_TTF ),

  MEDIA_IMAGE_APNG( IMAGE_APNG ),
  MEDIA_IMAGE_BMP( IMAGE_BMP ),
  MEDIA_IMAGE_GIF( IMAGE_GIF ),
  MEDIA_IMAGE_JPEG( IMAGE_JPEG,
                    of( "jpg", "jpe", "jpeg", "jfif", "pjpeg", "pjp" ) ),
  MEDIA_IMAGE_PNG( IMAGE_PNG ),
  MEDIA_IMAGE_PSD( IMAGE_PHOTOSHOP, of( "psd" ) ),
  MEDIA_IMAGE_SVG( IMAGE_SVG_XML, of( "svg" ) ),
  MEDIA_IMAGE_TIFF( IMAGE_TIFF, of( "tiff", "tif" ) ),
  MEDIA_IMAGE_WEBP( IMAGE_WEBP ),
  MEDIA_IMAGE_X_BITMAP( IMAGE_X_BITMAP, of( "xbm" ) ),
  MEDIA_IMAGE_X_PIXMAP( IMAGE_X_PIXMAP, of( "xpm" ) ),

  MEDIA_VIDEO_MNG( VIDEO_MNG, of( "mng" ) ),

  MEDIA_TEXT_MARKDOWN( TEXT_MARKDOWN, of(
    "md", "markdown", "mdown", "mdtxt", "mdtext", "mdwn", "mkd", "mkdown",
    "mkdn" ) ),
  MEDIA_TEXT_PLAIN( TEXT_PLAIN, of( "txt", "asc", "ascii", "text", "utxt" ) ),
  MEDIA_TEXT_R_MARKDOWN( TEXT_R_MARKDOWN, of( "Rmd" ) ),
  MEDIA_TEXT_R_XML( TEXT_R_XML, of( "Rxml" ) ),
  MEDIA_TEXT_XHTML( TEXT_XHTML, of( "xhtml" ) ),
  MEDIA_TEXT_XML( TEXT_XML ),
  MEDIA_TEXT_YAML( TEXT_YAML, of( "yaml", "yml" ) ),

  MEDIA_UNDEFINED( UNDEFINED, of( "undefined" ) );

  private final MediaType mMediaType;
  private final List<String> mExtensions;

  MediaTypeExtension( final MediaType mediaType ) {
    this( mediaType, of( mediaType.getSubtype() ) );
  }

  MediaTypeExtension(
    final MediaType mediaType, final List<String> extensions ) {
    assert mediaType != null;
    assert extensions != null;
    assert !extensions.isEmpty();

    mMediaType = mediaType;
    mExtensions = extensions;
  }

  public String getExtension() {
    return mExtensions.get( 0 );
  }

  public static MediaTypeExtension valueFrom( final MediaType mediaType ) {
    for( final var type : values() ) {
      if( type.isMediaType( mediaType ) ) {
        return type;
      }
    }

    return MEDIA_UNDEFINED;
  }

  boolean isMediaType( final MediaType mediaType ) {
    return mMediaType == mediaType;
  }

  static MediaType getMediaType( final String extension ) {
    final var sanitized = sanitize( extension );

    for( final var mediaType : MediaTypeExtension.values() ) {
      if( mediaType.isType( sanitized ) ) {
        return mediaType.getMediaType();
      }
    }

    return UNDEFINED;
  }

  private boolean isType( final String sanitized ) {
    for( final var extension : mExtensions ) {
      if( extension.equalsIgnoreCase( sanitized ) ) {
        return true;
      }
    }

    return false;
  }

  private static String sanitize( final String extension ) {
    return extension == null ? "" : extension.toLowerCase();
  }

  private MediaType getMediaType() {
    return mMediaType;
  }
}

用途:

// EXAMPLE -- Detect media type
//
final File image = new File( "filename.jpg" );
final MediaType mt = StreamMediaType.getMediaType( image );

// Tricky! The JPG could be a PNG in disguise.
if( mt.isType( MediaType.TypeName.IMAGE ) ) {

  if( mt == MediaType.IMAGE_PNG ) {
    // Nice try! Sneaky sneak.
  }
}

// EXAMPLE -- Get typical media type file name extension
//
final String ext = MediaTypeExtension.valueFrom( MediaType.IMAGE_SVG_XML ).getExtension();

// EXAMPLE -- Get media type from HTTP request
//
final var url = new URL( "https://localhost/path/file.ext" );
final var conn = (HttpURLConnection) url.openConnection();
final var contentType = conn.getContentType();
MediaType mediaType = valueFrom( contentType );

// Fall back to stream detection probe
if( mediaType == UNDEFINED ) {
  mediaType = StreamMediaType.getMediaType( conn.getInputStream() );
}

conn.disconnect();

你明白了。


简短的图书馆评论:


用于测试的示例音频、视频和图像文件:


1 “MIME 类型”是一个已弃用的术语。

于 2021-04-04T18:16:47.870 回答
0

如果您在 linux 操作系统上工作,则有一个命令行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'
于 2014-12-07T11:17:48.840 回答
0

在尝试了各种其他库后,我选择了 mime-util。

<groupId>eu.medsea.mimeutil</groupId>
      <artifactId>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);
于 2016-05-26T12:35:24.087 回答
0
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;
}
于 2016-11-23T13:26:18.497 回答
0
File file = new File(PropertiesReader.FILE_PATH);
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file);
URLConnection uconnection = file.toURL().openConnection();
mimeType = uconnection.getContentType();
于 2019-05-17T09:09:01.267 回答
0

我用下面的代码做到了。

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){

        }
    }
}
于 2019-07-31T20:33:50.153 回答
0

检查流或文件的魔术字节:

https://stackoverflow.com/a/65667558/3225638

它使用纯 Java,但需要您定义enum要检测的类型。

于 2021-01-13T05:51:10.010 回答
0

如果您想要一种将文件扩展名映射到 mime 类型的可靠(即一致)方式,我使用的是:

https://github.com/jjYBdx4IL/misc/blob/master/text-utils/src/main/java/com/github/jjYBdx4IL/utils/text/MimeType.java

它包括一个捆绑的 mime 类型数据库,并且通过使用数据库初始化“程序化”条目,基本上颠倒了 javax.activation 的 MimetypesFileTypeMap 类的逻辑。这样,库定义的类型总是优先于非捆绑资源中可能定义的类型。

于 2021-05-18T12:35:32.717 回答