【问题标题】:How to get the MIME Type of a .MSG file?如何获取 .MSG 文件的 MIME 类型?
【发布时间】:2015-09-13 07:17:55
【问题描述】:

我已经尝试过这些方法来查找文件的 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 类型,那么它将以文本/纯文本形式提供...

但我希望结果为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 类型呢?

【问题讨论】:

  • 您可以使用magic number 来检查文件并返回mimetype application/vnd.ms-outlook。对于 .msg:D0 CF 11 E0 A1 B1 1A E1
  • 你能否给我链接参考,你从哪里得到这个特殊的幻数......因为它存在于每个具有 CFB 配置的文件中,用于打包字节......
  • 我找到了here,但你是对的,这似乎不正确。
  • 您使用的.MSG文件是从哪个程序生成的?
  • 它是使用outlook创建的。

标签: java mime-types msg


【解决方案1】:

我不得不另谋出路。我发现 MS 文档(doc、docx、xls、xlsx、msg)是具有不同扩展名的压缩文件。我没有测试每个 MS 文件类型,因为它超出了当前范围

只需展开文件并:

Docx : 打开 [Content_Types].xml 并检查它是否包含“wordprocessingml”

XlsX : 打开 [Content_Types].xml 并检查它是否包含“spreadsheetml”

doc : 检查文件“WordDocument”

xls : 检查文件“工作簿”

消息:检查文件“__properties_version1.0”

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

【讨论】:

  • 我在 .Net 中工作,所以我不确定如何在 Java 中进行操作。在我的例子中,我们使用 7zip 应用程序来扩展文件。您可以(我假设)在您的环境中使用内置的压缩​​/解压缩模块。看看这个帖子。 stackoverflow.com/questions/9324933/…
【解决方案2】:

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

如果您可以假设没有人会到处玩并将 .doc 或 .xls 文件存储为 .msg 文件,那么您可以只读取标题的前 8 个字节并将其与文件扩展名结合起来,例如 @987654322 @

【讨论】:

  • 实际上我的应用程序是针对客户端的,在这里我不能假设任何事情......我已经尝试过读取 8 个字节的标题......对不起......
  • 然后不要读取 8 个字节并读取链接中提到的更多字节。链接清楚地解释了你如何从标题中找出文件是 excel。您可以尝试类似的标头读取来查找 .msg 文件。你检查我粘贴的链接了吗
【解决方案3】:

您可以尝试将文件转换为byte[],然后使用MimeMagic (Maven location here) 进行处理。类似的东西:

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

我不确定这是否会 100% 奏效,但尝试并不会死 :)

【讨论】:

    【解决方案4】:

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

    我尝试了不同的方法,不是全部在代码sn-p中:

    1. Java 7 Files.probeContentType(path)
    2. URLConnection通过文件名和内容类型猜测来检测mime
    3. JDK 6 JAF API javax.activation.MimetypesFileTypeMap
    4. MimeUtil 和我找到的所有可用的 MimeDetector 子类
    5. 阿帕奇蒂卡
    6. Apache POI 暂存器

    这里是测试类:

    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,如果文件格式不正确(通常为 @ 987654330@):

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

    【讨论】:

    • 它没有给我想要的解决方案....即使我获取一个文本文件并将其扩展名重命名为 .msg,并使用 taht 文件来获取 mime 类型,它也会给出输出作为 tika application/vnd.ms-outlook...谢谢你的工作...
    • 看看我更新的答案是否有帮助。最初的 tika 测试被使用 md.add(Metadata.RESOURCE_NAME_KEY, "test.msg"); 欺骗,这使得它依赖于文件扩展名
    • 您更新的代码也有同样的问题...对不起...请执行以下步骤...。 1. 创建一个文本文件。 2. 保存。 3. 将文件扩展名重命名为 .msg 4. 使用此文件运行程序....您将获得输出为 application/vnd.ms-outlook
    • 这正是我使用tikaMore方法所做的,结果是text/plain,请用上面的方法试一试
    • 还有其他方法吗...除了 tika api,因为它太大了.. 并且不能正确地达到目的
    猜你喜欢
    • 2014-01-30
    • 2018-12-01
    • 2014-09-28
    • 2011-04-20
    • 2014-05-19
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 2011-05-27
    相关资源
    最近更新 更多