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

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


当前回答

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

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

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

其他回答

JAF API是JDK 6的一部分。看看javax。激活包。

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

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

MultipartFile文件;

org.springframework.web.multipart.MultipartFile

文件。getContentType ();

我找不到任何东西来检查视频/mp4 MIME类型,所以我做了自己的解决方案。 我偶然发现维基百科是错误的,并且00 00 00 18 66 74 79 70 69 73 6F 6D文件签名是不正确的。第四个字节(18)和所有70个字节(不包括)在其他有效的mp4文件中进行了相当多的更改后。

这段代码本质上是URLConnection的复制/粘贴。guessContentTypeFromStream代码,但为视频/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文件。

编辑:这是一个有用的链接(如果它仍然在线),在那里你可以找到许多类型的样本。我没有这些视频,也不知道谁有,但它们对测试上面的代码很有用。

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();
}

请注意,meditype .detect(…)不能直接使用(TIKA-1120)。更多提示请访问https://tika.apache.org/1.24/detection.html。

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