如何获取.MSG文件的MIME类型?

时间:2015-06-26 10:57:03

标签: java mime-types msg

我尝试过这些方法来查找文件的MIME类型......

Path source = Paths
                .get("C://Users/akash/Desktop/FW Internal release of MSTClient-Server5.02.04_24.msg");
        System.out.println(Files.probeContentType(source));

以上代码返回null ...
如果我使用Apache的TIKA API来获取MIME类型,那么它将它作为text / plain ...

但我希望结果为application/vnd.ms-outlook

更新

我还使用MIME-Util.jar如下代码...

MimeUtil2 mimeUtil = new MimeUtil2();
        mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
        RandomAccessFile file1 = new RandomAccessFile(
                "C://Users/akash/Desktop/FW Internal release of MSTClient-Server5.02.04_24.msg",
                "r");
        System.out.println(file1.length());
        byte[] file = new byte[624128];
        file1.read(file, 0, 624128);
        String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();

这使我的输出为application/msword

更新

Tika API超出范围,因为它太大而无法包含在项目中......

那我怎样才能找到MIME类型?

4 个答案:

答案 0 :(得分:6)

我尝试了一些可能的方法,并且使用tika给出了您期望的结果,我没有看到您使用的代码,所以我无法仔细检查它。

我尝试了不同的方法,而不是全部在代码段中:

  1. Java 7 Files.probeContentType(path)
  2. URLConnection mime检测文件名和内容类型猜测
  3. JDK 6 JAF API javax.activation.MimetypesFileTypeMap
  4. MimeUtil与MimeDetector的所有可用子类我找到了
  5. Apache Tika
  6. Apache POI暂存器
  7. 这里是测试类:

    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.net.URLConnection;
    import java.util.Collection;
    
    import javax.activation.MimetypesFileTypeMap;
    
    import org.apache.tika.detect.Detector;
    import org.apache.tika.metadata.Metadata;
    import org.apache.tika.mime.MediaType;
    import org.apache.tika.parser.AutoDetectParser;
    
    import eu.medsea.mimeutil.MimeUtil;
    
    public class FindMime {
    
        public static void main(String[] args) {
            File file = new File("C:\\Users\\qwerty\\Desktop\\test.msg");
    
            System.out.println("urlConnectionGuess " + urlConnectionGuess(file));
    
            System.out.println("fileContentGuess " + fileContentGuess(file));
    
            MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
    
            System.out.println("mimeTypesMap.getContentType " + mimeTypesMap.getContentType(file));
    
            System.out.println("mimeutils " + mimeutils(file));
    
            System.out.println("tika " + tika(file));
    
        }
    
        private static String mimeutils(File file) {
            try {
                MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
                MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.ExtensionMimeDetector");
    //          MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.OpendesktopMimeDetector");
                MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.WindowsRegistryMimeDetector");
    //          MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.TextMimeDetector");
                InputStream is = new BufferedInputStream(new FileInputStream(file));
                Collection<?> mimeTypes = MimeUtil.getMimeTypes(is);
                return mimeTypes.toString();
            } catch (Exception e) {
                // TODO: handle exception
            }
            return null;
        }
    
        private static String tika(File file) {
            try {
                InputStream is = new BufferedInputStream(new FileInputStream(file));
                AutoDetectParser parser = new AutoDetectParser();
                Detector detector = parser.getDetector();
                Metadata md = new Metadata();
                md.add(Metadata.RESOURCE_NAME_KEY, "test.msg");
                MediaType mediaType = detector.detect(is, md);
                return mediaType.toString();
            } catch (Exception e) {
                // TODO: handle exception
            }
            return null;
        }
    
        private static String urlConnectionGuess(File file) {
            String mimeType = URLConnection.guessContentTypeFromName(file.getName());
            return mimeType;
        }
    
        private static String fileContentGuess(File file) {
            try {
                InputStream is = new BufferedInputStream(new FileInputStream(file));
                return URLConnection.guessContentTypeFromStream(is);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
    }
    

    这是输出:

    urlConnectionGuess null
    fileContentGuess null
    mimeTypesMap.getContentType application/octet-stream
    mimeutils application/msword,application/x-hwp
    tika application/vnd.ms-outlook
    

    已更新我添加了此方法以测试Tika的其他方式:

    private static void tikaMore(File file) {
        Tika defaultTika = new Tika();
        Tika mimeTika = new Tika(new MimeTypes());
        Tika typeTika = new Tika(new TypeDetector());
        try {
            System.out.println(defaultTika.detect(file));
            System.out.println(mimeTika.detect(file));
            System.out.println(typeTika.detect(file));
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
    

    使用没有扩展名的msg文件进行测试:

    application/vnd.ms-outlook
    application/octet-stream
    application/octet-stream
    

    使用重命名为msg的txt文件进行测试:

    text/plain
    text/plain
    application/octet-stream
    

    在这种情况下,使用空构造函数的最简单方法似乎是最可靠的。

    更新您可以使用Apache POI暂存器创建自己的检查器,例如,这是获取消息mime的简单实现,如果文件格式不正确,则为null(通常为{ {1}}):

    org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature

答案 1 :(得分:3)

从@Duffydake的评论中得到启示,我尝试阅读神奇的数字。同意MS文件头的前8个字节保持相同D0 CF 11 E0 A1 B1 1A E1(有趣的是看前四个字节看起来像eDoCFilE),但你可以检查这个link如何理解完整的头并找到文件类型。 (例如,在链接中找到一个excel文件,但您可以使用类似的字节读取来查找msg文件类型)

如果您可以假设没有人会玩,并将.doc或.xls文件存储为.msg文件,那么您只需读取标头的前8个字节并将其与文件扩展名组合,例如{{ 1}}

答案 2 :(得分:2)

您可以尝试将文件转换为MimeMagic,然后使用byte[] data = FileUtils.toByteArray("file.msg"); MagicMatch match = Magic.getMagicMatch(data); String mimeType = match.getMimeType(); Maven location here)来处理它。这样的事情:

{{1}}

我不确定这会100%有效,但尝试不会死:)

答案 3 :(得分:0)

我必须得到另一种解决方法。我发现MS文档(doc,docx,xl​​s,xlsx,msg)是具有不同扩展名的压缩文件。我没有测试每个MS文件类型,因为它超出了当前范围

只需展开文件即可:

Docx:打开[Content_Types] .xml并检查它是否包含&#34; wordprocessingml&#34;

XlsX:打开[Content_Types] .xml并检查它是否包含&#34; spreadsheetml&#34;

doc:检查文件&#34; WordDocument&#34;

xls:检查文件&#34;工作簿&#34;

msg:检查文件&#34; __ properties_version1.0&#34;

我仍在测试msg以查看是否有更好的用法,但此文件存在于已发送和未发送的消息中,因此我假设它可以安全使用。