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

Java 如何获取.MSG文件的MIME类型?,java,mime-types,msg,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类型,那么它

我尝试了以下方法来查找文件的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类型呢?

我尝试了一些可能的方法,使用tika会得到您期望的结果,我看不到您使用的代码,因此无法再次检查它

我尝试了不同的方法,但并非都在代码片段中:

  • Java 7
    Files.probeContentType(路径)
  • URLConnection
    mime检测来自文件名和内容类型猜测
  • JDK 6 JAF API
    javax.activation.MimetypesFileTypeMap
  • MimeUtil和我找到的
    MimeDetector
    的所有可用子类
  • 阿帕奇提卡
  • ApachePOI草稿行
  • 下面是测试类:

    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;
            }
        }
    
    }
    
    更新了我添加了此方法来测试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(通常
    org.Apache.POI.poifs.filesystem.NotOLE2FileException:无效的头签名
    ):


    您可以尝试将文件转换为
    byte[]
    ,然后使用
    MimeMagic
    ()来处理它。诸如此类:

    byte[] data = FileUtils.toByteArray("file.msg");
    MagicMatch match = Magic.getMagicMatch(data);
    String mimeType = match.getMimeType();
    

    我真的不确定这是否能100%奏效,但尝试并不是死亡:)

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


    如果您可以假设没有人将.doc或.xls文件存储为.msg文件,那么您只需读取头的前8个字节并将其与文件扩展名组合,例如
    If(fileExtension.equals(.msg)&&hexHeaderString.equals('D0 CF 11 E0 A1 B1 1A E1'){mimeType==“application/vnd.ms outlook”}

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

    只需展开文件并执行以下操作:

    Docx:打开[Content\u Types].xml并检查它是否包含“wordprocessingml”

    XlsX:打开[Content\u Types].xml并检查它是否包含“spreadsheetml”

    文档:检查文件“WordDocument”

    xls:检查文件“工作簿”

    消息:检查文件“\uuuu属性\u版本1.0”


    我仍在测试msg,看看是否有更好的东西可以使用,但是这个文件存在于已发送和未发送的消息中,所以我认为它可以安全使用。

    您可以使用来检查文件并返回mimetype
    应用程序/vnd.ms outlook
    。For.msg:
    D0 CF 11 E0 A1 B1 1A E1
    您能给我一个链接参考吗你得到了这个特别的神奇数字…因为它存在于每个文件中,每个文件都有CFB配置来打包字节…我找到了它,但你是对的,这似乎不正确。你使用的.MSG文件是从哪个程序生成的?它是用outlook创建的。它没有给我想要的解决方案…即使我使用文本文件d将其扩展名重命名为.msg,并使用taht文件获取mime类型,然后它也将输出为tika application/vnd.ms outlook…感谢您的工作…看看我的更新答案是否有帮助。最初的tika测试被使用
    md.add(Metadata.RESOURCE\u NAME\u KEY,“test.msg”)愚弄了;
    这使得它依赖于文件扩展名您更新的代码也有同样的问题…抱歉…执行以下步骤…1.创建一个文本文件。2.保存它。3.将文件扩展名重命名为.msg 4.使用此文件运行程序…您将以application/vnd.ms-outlook的形式获得输出。这正是我使用
    tikaMore
    方法所做的结果是
    text/plain
    ,请尝试一下上面的方法有没有其他方法…除了tika api之外,因为它太大了..而且没有正确的用途实际上我的应用程序是为客户机设计的,在这里我不能假设任何东西…我已经尝试了读取8个字节的头..对不起..那么不要读取链接中提到的8个字节,而是读取更多字节。链接清楚地解释了如何从页眉看出文件是excel。您可以尝试类似的页眉读取来查找.msg文件。您是否检查了我在.Net中使用的链接,所以我不确定如何在Java中执行此操作。在我的示例中,我们使用7zip应用程序来扩展f你可以(我假设)在你的环境中使用内置的压缩/解压缩模块。
    import org.apache.poi.hsmf.MAPIMessage;
    
    public class PoiMsgMime {
    
        public String getMessageMime(String fileName) {
            try {
                new MAPIMessage(fileName);
                return "application/vnd.ms-outlook";
            } catch (Exception e) {
                return null;
            }
        }
    }
    
    byte[] data = FileUtils.toByteArray("file.msg");
    MagicMatch match = Magic.getMagicMatch(data);
    String mimeType = match.getMimeType();