java - configurar - ¿Cómo obtener el tipo MIME de un archivo.MSG?
configurar mime types en iis (4)
He intentado estas formas de encontrar el tipo MIME de un archivo ...
Path source = Paths
.get("C://Users/akash/Desktop/FW Internal release of MSTClient-Server5.02.04_24.msg");
System.out.println(Files.probeContentType(source));
El código anterior devuelve null
...
Y si utilizo la API TIKA de Apache para obtener el tipo MIME, se lo da como texto / plano ...
Pero quiero el resultado como application/vnd.ms-outlook
ACTUALIZAR
También usé MIME-Util.jar
como sigue con el código ...
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();
Esto me da salida como application/msword
ACTUALIZACIÓN :
La API de Tika está fuera del alcance, ya que es demasiado grande para incluirla en el proyecto ...
Entonces, ¿cómo puedo encontrar el tipo MIME?
Lo que podría hacer es tratar de convertir el archivo a byte[]
y luego usar MimeMagic
( ubicación de Maven aquí ) para manejarlo. Algo como eso:
byte[] data = FileUtils.toByteArray("file.msg");
MagicMatch match = Magic.getMagicMatch(data);
String mimeType = match.getMimeType();
No estoy realmente seguro de que esto funcione al 100%, pero intentarlo no es morir :)
Probé algunas de las formas posibles y usar tika da el resultado que esperaba, no veo el código que usó, así que no puedo verificarlo dos veces.
Probé diferentes maneras, no todas en el fragmento de código:
- Java 7
Files.probeContentType(path)
-
URLConnection
mimeURLConnection
partir del nombre del archivo y la adivinación del tipo de contenido - JDK 6 JAF API
javax.activation.MimetypesFileTypeMap
- MimeUtil con todas las subclases disponibles de
MimeDetector
que encontré - Apache tika
- Bloc de notas apache POI
Aquí la clase de prueba:
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;
}
}
}
y esta es la salida:
urlConnectionGuess null
fileContentGuess null
mimeTypesMap.getContentType application/octet-stream
mimeutils application/msword,application/x-hwp
tika application/vnd.ms-outlook
Actualizado , agregué este método para probar otras formas con 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
}
}
probado con un archivo msg sin extensión:
application/vnd.ms-outlook
application/octet-stream
application/octet-stream
probado con un archivo txt renombrado a msg:
text/plain
text/plain
application/octet-stream
Parece que la forma más sencilla de usar el constructor vacío es la más confiable en este caso.
Actualice puede hacer su propio verificador utilizando el bloc de notas de Apache POI, por ejemplo, esta es una implementación simple para obtener el mimo del mensaje o nulo si el archivo no tiene el formato adecuado (generalmente 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;
}
}
}
Siguiendo el ejemplo de @Duffydake, intenté leer los números mágicos. Se acordó que los primeros 8 bytes del encabezado de los archivos MS siguen siendo los mismos D0 CF 11 E0 A1 B1 1A E1 (es interesante ver los primeros cuatro bytes que parecen eDoCFilE) pero puede consultar este link para entender el encabezado completo y encontrar el tipo de archivo. (por ejemplo, en el enlace encuentra un archivo de Excel, pero puede usar la lectura de bytes similar para encontrar el tipo de archivo msg)
Si puede suponer que nadie va a jugar y almacenar el archivo .doc o .xls como archivo .msg, puede leer los primeros 8 bytes del encabezado y combinarlo con la extensión del archivo, por ejemplo, if(fileExtension.equals(".msg")&&hexHeaderString.equals(''D0 CF 11 E0 A1 B1 1A E1''){mimeType=="application/vnd.ms-outlook"}
Tuve que conseguir otra solución. Lo que encontré fue que los documentos de MS (doc, docx, xls, xlsx, msg) son archivos comprimidos con una extensión diferente. No he probado todos los tipos de archivo de MS porque están fuera del alcance actual
Simplemente expanda el archivo y:
Docx: abra [Content_Types] .xml y verifique si contiene "wordprocessingml"
XlsX: abre [Content_Types] .xml y comprueba si contiene "hoja de cálculo"
doc: compruebe el archivo "documento de palabra"
xls: compruebe el archivo "libro de trabajo"
msg: compruebe el archivo "__properties_version1.0"
Todavía estoy probando msg para ver si hay algo mejor de usar, pero este archivo existe en los mensajes enviados y no enviados, por lo que asumo que es seguro usarlo.