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

How to get the MIME Type of a .MSG file?

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

1
2
3
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如下代码...

1
2
3
4
5
6
7
8
9
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(path)
  • 从文件名和内容类型猜测中URLConnection mime检测
  • JDK 6 JAF API javax.activation.MimetypesFileTypeMap
  • 我发现MimeUtil具有MimeDetector的所有可用子类
  • 阿帕奇·蒂卡(Apache Tika)
  • Apache POI暂存器
  • 这里是测试类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    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;
            }
        }

    }

    这是输出:

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

    更新后,我添加了此方法以使用Tika测试其他方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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文件进行了测试:

    1
    2
    3
    application/vnd.ms-outlook
    application/octet-stream
    application/octet-stream

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

    1
    2
    3
    text/plain
    text/plain
    application/octet-stream

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

    更新您可以使用Apache POI暂存器进行自己的检查,例如,这是一种获取消息的哑剧的简单实现;如果文件格式不正确(通常为org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature),则为null:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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;
            }
        }
    }


    从@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"}


    您可以尝试将文件转换为byte[],然后使用MimeMagic(此处为Maven位置)进行处理。像这样:

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

    我不确定这是否可以100%使用,但是尝试不死:)


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

    只需扩展文件,然后:

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

    XlsX:打开[Content_Types] .xml并检查其是否包含" spreadsheetml"

    doc:检查文件" WordDocument"

    xls:检查文件"工作簿"

    msg:检查文件" __properties_version1.0"

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