如何获取 .MSG 文件的 MIME 类型?
How to get the MIME Type of a .MSG file?
我试过这些方法来查找文件的 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));
以上代码returnsnull
...
如果我使用 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(path)
URLConnection
根据文件名和内容类型猜测的 mime 检测
- JDK 6 JAF API
javax.activation.MimetypesFileTypeMap
- MimeUtil 以及
MimeDetector
的所有可用子class 我找到了
- 阿帕奇蒂卡
- Apache POI 暂存器
这里是测试class:
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
在这种情况下,似乎使用空构造函数的最简单方法是最可靠的。
Update 您可以使用 Apache POI 暂存器制作您自己的检查器,例如,这是一个简单的实现来获取消息的 mime,如果文件不在正确的格式(通常是 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;
}
}
}
您可以尝试将文件转换为byte[]
,然后使用MimeMagic
(Maven location here) 来处理它。类似的东西:
byte[] data = FileUtils.toByteArray("file.msg");
MagicMatch match = Magic.getMagicMatch(data);
String mimeType = match.getMimeType();
我不确定这是否会 100% 有效,但尝试不会死:)
从@Duffydake 的评论中得到启发,我尝试阅读神奇的数字。同意 MS 文件 header 的前 8 个字节保持不变 D0 CF 11 E0 A1 B1 1A E1(有趣的是看到前四个字节看起来像 eDoCFilE)但是你可以检查这个 link 如何理解完整header 并找到文件类型。 (例如,在 link 中找到一个 excel 文件,但您可以使用类似的字节读取来查找 msg 文件类型)
如果你可以假设没有人会玩游戏并将.doc 或.xls 文件存储为.msg 文件,那么你可以只读取header 的前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_Types].xml 并检查它是否包含 "wordprocessingml"
XlsX : 打开 [Content_Types].xml 并检查它是否包含 "spreadsheetml"
doc : 检查文件 "WordDocument"
xls : 检查文件 "Workbook"
msg:检查文件“__properties_version1.0”
我仍在测试 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));
以上代码returnsnull
...
如果我使用 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(path)
URLConnection
根据文件名和内容类型猜测的 mime 检测- JDK 6 JAF API
javax.activation.MimetypesFileTypeMap
- MimeUtil 以及
MimeDetector
的所有可用子class 我找到了 - 阿帕奇蒂卡
- Apache POI 暂存器
这里是测试class:
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
在这种情况下,似乎使用空构造函数的最简单方法是最可靠的。
Update 您可以使用 Apache POI 暂存器制作您自己的检查器,例如,这是一个简单的实现来获取消息的 mime,如果文件不在正确的格式(通常是 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;
}
}
}
您可以尝试将文件转换为byte[]
,然后使用MimeMagic
(Maven location here) 来处理它。类似的东西:
byte[] data = FileUtils.toByteArray("file.msg");
MagicMatch match = Magic.getMagicMatch(data);
String mimeType = match.getMimeType();
我不确定这是否会 100% 有效,但尝试不会死:)
从@Duffydake 的评论中得到启发,我尝试阅读神奇的数字。同意 MS 文件 header 的前 8 个字节保持不变 D0 CF 11 E0 A1 B1 1A E1(有趣的是看到前四个字节看起来像 eDoCFilE)但是你可以检查这个 link 如何理解完整header 并找到文件类型。 (例如,在 link 中找到一个 excel 文件,但您可以使用类似的字节读取来查找 msg 文件类型)
如果你可以假设没有人会玩游戏并将.doc 或.xls 文件存储为.msg 文件,那么你可以只读取header 的前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_Types].xml 并检查它是否包含 "wordprocessingml"
XlsX : 打开 [Content_Types].xml 并检查它是否包含 "spreadsheetml"
doc : 检查文件 "WordDocument"
xls : 检查文件 "Workbook"
msg:检查文件“__properties_version1.0”
我仍在测试 msg 是否有更好用的东西,但是这个文件存在于已发送和未发送的消息中,所以我假设它可以安全使用。