Ale*_*lue 14 java file-type mime-types
我正在为程序添加一些功能,以便我可以通过读取MIME数据来准确地确定文件类型.我已经尝试过几种方法:
方法1:
javax.activation.FileDataSource
FileDataSource ds = new FileDataSource("~\\Downloads\\777135_new.xls");
String contentType = ds.getContentType();
System.out.println("The MIME type of the file is: " + contentType);
//output = The MIME type of the file is: application/octet-stream
Run Code Online (Sandbox Code Playgroud)
方法2:
import net.sf.jmimemagic.*;
try
{
RandomAccessFile f = new RandomAccessFile("~\\Downloads\\777135_new.xls", "r");
byte[] fileBytes = new byte[(int)f.length()];
f.read(fileBytes);
MagicMatch match = Magic.getMagicMatch(fileBytes);
System.out.println("The Mime type is: " + match.getMimeType());
}
catch(Exception e)
{
System.out.println(e);
}
//output = The Mime type is: application/msword
Run Code Online (Sandbox Code Playgroud)
方法3:
import eu.medsea.mimeutil.*;
MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
File f = new File ("~\\Downloads\\777135_new.xls");
Collection<?> mimeTypes = MimeUtil.getMimeTypes(f);
String mimeType = MimeUtil.getFirstMimeType(mimeTypes.toString()).toString();
String subMimeType = MimeUtil.getSubType(mimeTypes.toString());
System.out.println("The Mime type is: " + mimeTypes + ", " + mimeType + ", " + subMimeType);
//output = The Mime type is: application/msword, application/msword, msword
Run Code Online (Sandbox Code Playgroud)
我在http://www.rgagnon.com/javadetails/java-0487.html找到了这三种方法.但是我的问题是,我正在测试这些方法的文件是我创建的文件,因此我知道它是一个Excel文件,但是仍然所有三种方法都错误地将类型作为msword而不是第一种方法我认为是因为该方法使用的内置FileTypeMap中的文件类型数量有限.
我已经浏览了一下,有些人说这是因为在文件中检测到偏移的方式,因此内容类型被错误地拾取,正如本维基中在PHP中检测文件类型所指出的那样.不幸的是,维基然后继续使用扩展来确定文件类型,这不是我想要做的,因为它不可靠.
任何人都可以指出我正确的方向,将在Java中正确检测文件类型吗?
干杯,阿列克谢蓝.
编辑:看起来没有特定的解决方案,因为@IronMensan在下面的评论中说.我确实找到了这个非常有趣的研究论文,它以一些方式应用机器学习来帮助解决这个问题,但似乎没有一个完整的证明答案.我认为我最好的选择是尝试将文件传递给excel文件阅读器并捕获任何不正确的格式异常.
rod*_*cia 28
到目前为止,我发现确定文件MIME类型的最准确的工具是Apache Tika.这是我目前使用的略有修改(使用Tika版本1.0)
import org.apache.tika.detect.DefaultDetector;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MimeTypes;
private static final Detector DETECTOR = new DefaultDetector(
MimeTypes.getDefaultMimeTypes());
public static String detectMimeType(final File file) throws IOException {
TikaInputStream tikaIS = null;
try {
tikaIS = TikaInputStream.get(file);
/*
* You might not want to provide the file's name. If you provide an Excel
* document with a .xls extension, it will get it correct right away; but
* if you provide an Excel document with .doc extension, it will guess it
* to be a Word document
*/
final Metadata metadata = new Metadata();
// metadata.set(Metadata.RESOURCE_NAME_KEY, file.getName());
return DETECTOR.detect(tikaIS, metadata).toString();
} finally {
if (tikaIS != null) {
tikaIS.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于Tika将使用魔术数字,但在不确定时也会查看文件的内容,这个过程可能需要一点时间(我的PC花了3.268秒来检查15个文件).
另外,不要犯同样的错误.如果你得到tika-core JAR,你也应该得到tika解析器 JAR.如果你没有获得tika-parsers你将不会得到任何例外,你将无法准确地获得MIME类型,因此包含它是非常重要的.
另一种方法是获取tika-app JAR,它包含tika-core,tika-parsers和所有依赖项(它们很多:poi,poi-ooxml,xmlbeans,commons-compress,仅举几例).