Подтвердить что ты не робот

Как получить MIME-тип файла .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...
И если я использую API TIKA из Apache, чтобы получить MIME-тип, он дает его как текстовое/обычное...

Но я хочу, чтобы результат был application/vnd.ms-outlook

UPDATE

Я также использовал 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

UPDATE

Tika API выходит за рамки, поскольку он слишком велик для включения в проект...

Итак, как я могу найти тип MIME?

4b9b3361

Ответ 1

Я пробовал некоторые из возможных способов, и использование tika дает ожидаемый результат, я не вижу код, который вы использовали, поэтому я не могу его дважды проверить.

Я пробовал разные способы, не все в фрагменте кода:

  • Java 7 Files.probeContentType(path)
  • URLConnection обнаружение mime из имени файла и догадки типа контента
  • JDK 6 API JAF javax.activation.MimetypesFileTypeMap
  • MimeUtil со всем доступным подклассом MimeDetector Я нашел
  • Apache Tika
  • Блокнот 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

протестирован с txt файлом, переименованным в msg:

text/plain
text/plain
application/octet-stream

кажется, что самый простой способ с помощью пустого конструктора является самым надежным в этом случае.

Обновить вы можете сделать свой собственный чекер с помощью блокнота Apache POI, например, это простая реализация, чтобы получить mime сообщения или null, если файл не находится в правильном формате (обычно org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature):

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

Ответ 2

Что вы можете сделать, это попытаться преобразовать файл в byte[], а затем использовать MimeMagic (местоположение Maven здесь) для обработки Это. Что-то вроде этого:

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

Я не уверен, что это будет работать на 100%, но попробовать не умереть:)

Ответ 3

Взяв реплику из комментария @Duffydake, я пробовал читать магические числа. Согласились, что первые 8 байтов заголовка для файлов MS остаются такими же D0 CF 11 E0 A1 B1 1A E1 (Интересно видеть первый четыре байта, который выглядит как eDoCFilE), но вы можете проверить это link, как понять полный заголовок и найти тип файла. (например, в ссылке находит файл 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"}

Ответ 4

Мне нужно было найти еще один способ обхода проблемы. Я обнаружил, что документы MS (doc, docx, xls, xlsx, msg) - это сжатые файлы с другим расширением. Я не тестировал каждый тип файла MS, поскольку он находится за пределами текущей области

Просто разверните файл и:

Docx: откройте [Content_Types].xml и проверьте, содержит ли он "wordprocessingml"

XlsX: откройте [Content_Types].xml и проверьте, содержит ли он "spreadsheetml"

doc: проверьте файл "WordDocument"

xls: проверьте файл "Рабочая книга"

msg: проверьте файл "__properties_version1.0"

Я все еще проверяю msg, чтобы узнать, есть ли что-то лучше для использования, но этот файл существует в отправленных и неотправленных сообщениях, поэтому я предполагаю, что он безопасен в использовании.