Obtenir le type Mime D'un fichier en Java
je me demandais juste comment la plupart des gens récupèrent un type mime d'un fichier en Java? Jusqu'à présent, j'ai essayé deux utils: JMimeMagic
et Mime-Util
.
le premier m'a donné des exceptions de mémoire, le second ne ferme pas ses flux correctement. Je me demandais juste si quelqu'un d'autre avait une méthode/bibliothèque qu'il utilisait et fonctionnait correctement?
18 réponses
en Java 7, vous pouvez maintenant utiliser Files.probeContentType(path)
.
malheureusement,
mimeType = file.toURL().openConnection().getContentType();
ne fonctionne pas, puisque cette utilisation d'URL laisse un fichier verrouillé, de sorte que, par exemple, il est indélébile.
cependant, vous avez ceci:
mimeType= URLConnection.guessContentTypeFromName(file.getName());
et aussi ce qui suit, qui a l'avantage d'aller au-delà de la simple utilisation de l'extension de fichier, et jette un oeil au contenu
InputStream is = new BufferedInputStream(new FileInputStream(file));
mimeType = URLConnection.guessContentTypeFromStream(is);
//...close stream
Toutefois, comme le suggère le commentaire ci-dessus, le tableau de mime-types est assez limité, ne comprenant pas, par exemple, MSWord et PDF. Donc, si vous voulez généraliser, vous aurez besoin d'aller au-delà des bibliothèques intégrées, en utilisant, par exemple, Mime-Util (qui est une grande bibliothèque, en utilisant à la fois l'extension du fichier et le contenu).
L'API JAF fait partie de JDK 6. Regardez le paquet javax.activation
.
les classes les plus intéressantes sont javax.activation.MimeType
- un support de type MIME réel - et javax.activation.MimetypesFileTypeMap
- classe dont l'instance peut résoudre le type MIME comme chaîne de caractères pour un fichier:
String fileName = "/path/to/file";
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
// only by file name
String mimeType = mimeTypesMap.getContentType(fileName);
// or by actual File instance
File file = new File(fileName);
mimeType = mimeTypesMap.getContentType(file);
Avec Apache Tika vous avez seulement besoin de trois lignes de code :
File file = new File("/path/to/file");
Tika tika = new Tika();
System.out.println(tika.detect(file));
si vous avez une console groovy, il suffit de coller et d'exécuter ce code pour jouer avec:
@Grab('org.apache.tika:tika-core:1.14')
import org.apache.tika.Tika;
def tika = new Tika()
def file = new File("/path/to/file")
println tika.detect(file)
gardez à l'esprit que ses API sont riches, il peut Parser "n'importe quoi". À partir de tika-core 1.14, vous avez:
String detect(byte[] prefix)
String detect(byte[] prefix, String name)
String detect(File file)
String detect(InputStream stream)
String detect(InputStream stream, Metadata metadata)
String detect(InputStream stream, String name)
String detect(Path path)
String detect(String name)
String detect(URL url)
Voir la apidocs pour plus d'informations.
Apache Tika offre dans tika-core une détection de type mime basée sur des marqueurs magiques dans le préfixe stream. tika-core
ne récupère pas d'autres dépendances, ce qui le rend aussi léger que l'utilitaire de détection de type Mime actuellement non maintenu .
exemple de code Simple (Java 7), en utilisant les variables theInputStream
et theFileName
try (InputStream is = theInputStream;
BufferedInputStream bis = new BufferedInputStream(is);) {
AutoDetectParser parser = new AutoDetectParser();
Detector detector = parser.getDetector();
Metadata md = new Metadata();
md.add(Metadata.RESOURCE_NAME_KEY, theFileName);
MediaType mediaType = detector.detect(bis, md);
return mediaType.toString();
}
S'il vous plaît notez que MediaType.détecter.(..) ne peut pas être utilisé directement ( TIKA-1120 ). Plus de conseils sont fournis à https://tika.apache.org/0.10/detection.html .
si vous êtes un développeur Android, vous pouvez utiliser une classe utilitaire android.webkit.MimeTypeMap
qui mappe les types MIME aux extensions de fichiers et vice versa.
l'extrait de code suivant peut vous aider.
private static String getMimeType(String fileUrl) {
String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
à Partir de roseindia :
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");
si vous êtes bloqué avec java 5-6 alors cette classe d'utilitaire de servoy open source produit
vous n'avez besoin de cette fonction que
public static String getContentType(byte[] data, String name)
Il sonde les premiers octets du contenu et retourne les types de contenu basé sur ce contenu et non par extension de fichier.
je me demandais juste comment la plupart des gens récupèrent un type mime d'un fichier en Java?
j'ai publié mon paquet Java SimpleMagic qui permet la détermination du type de contenu (mime-type) à partir des fichiers et des tableaux d'octets. Il est conçu pour lire et exécuter les fichiers magic de la commande Unix(1) qui font partie de la plupart des configurations ~Unix OS.
J'ai essayé Apache Tika mais c'est énorme avec des tonnes de dépendances, URLConnection
n'utilise pas les octets des fichiers, et MimetypesFileTypeMap
regarde aussi juste les noms de fichiers.
avec SimpleMagic vous pouvez faire quelque chose comme:
// create a magic utility using the internal magic file
ContentInfoUtil util = new ContentInfoUtil();
// if you want to use a different config file(s), you can load them by hand:
// ContentInfoUtil util = new ContentInfoUtil("/etc/magic");
...
ContentInfo info = util.findMatch("/tmp/upload.tmp");
// or
ContentInfo info = util.findMatch(inputStream);
// or
ContentInfo info = util.findMatch(contentByteArray);
// null if no match
if (info != null) {
String mimeType = info.getMimeType();
}
j'ai essayé plusieurs façons de le faire, y compris les premières dites par @Joshua Fox. Mais certains ne reconnaissent pas les mimétypes fréquents comme pour les fichiers PDF, et d'autres ne pouvaient pas être fiables avec les faux fichiers (j'ai essayé avec un fichier RAR avec extension changée en TIF). La solution que j'ai trouvée, comme le dit aussi @Joshua Fox de manière superficielle, est d'utiliser MimeUtil2 , comme ceci:
MimeUtil2 mimeUtil = new MimeUtil2();
mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();
Il est préférable d'utiliser deux couches de validation de téléchargement de fichiers.
tout d'abord, vous pouvez vérifier pour le mimeType et de le valider.
ensuite, vous devriez chercher à convertir les 4 premiers octets de votre fichier en hexadécimal et ensuite comparer avec les nombres magiques. Alors il sera vraiment sûr moyen de vérifier la validation de fichier.
à la carte À puce avec mon 5 cents:
TL, DR
j'utilise MimetypesFileTypeMap et d'ajouter tout de mime qui n'est pas là et j'ai précisément besoin, en mime.types de fichiers.
et maintenant, le long lire:
tout d'abord, la liste des types MIME est énorme , voir ici: https://www.iana.org/assignments/media-types/media-types.xhtml
j'aime utiliser les installations standard fournies par JDK d'abord, et si cela ne fonctionne pas, je vais aller chercher autre chose.
déterminer le type de fichier à partir de l'extension de fichier
depuis 1.6, Java a MimetypesFileTypeMap, comme indiqué dans l'une des réponses ci-dessus, et c'est la façon la plus simple de déterminer le type mime:
new MimetypesFileTypeMap().getContentType( fileName );
dans son implémentation vanille cela ne fait pas beaucoup (i.e. il fonctionne pour .html mais ce n'est pas pour .png). Il est cependant très simple d'ajouter n'importe quel type de contenu dont vous avez besoin:
- créer un fichier nommé 'mime.types 'dans le dossier META-INF de votre projet
- ajouter une ligne pour chaque type mime dont vous avez besoin et l'implémentation par défaut ne fournit pas (il y a des centaines de types mime et la liste croît avec le temps).
exemples d'entrées pour les fichiers png et js:
image/png png PNG
application/javascript js
pour mime.types format de fichier, Voir plus de détails ici: https://docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.html
déterminer le type de fichier à partir du contenu du fichier
depuis 1.7, Java a java.nio.fichier.le spi.FileTypeDetector , qui définit un API standard pour déterminer un type de fichier dans implementation specific way .
pour obtenir le type mime d'un fichier, il vous suffit d'utiliser Files et de le faire dans votre code:
Files.probeContentType(Paths.get("either file name or full path goes here"));
la définition de L'API prévoit des fonctionnalités qui prennent en charge soit la détermination du type mime du fichier à partir du nom du fichier, soit à partir du contenu du fichier (octets magiques). C'est pourquoi la méthode probeContentType() lance IOException, dans le cas où une implémentation de cette API utilise le chemin qui lui est fourni pour réellement essayer d'ouvrir le fichier qui lui est associé.
encore une fois, vanille mise en œuvre de ce (celui qui vient avec JDK) laisse beaucoup à désirer.
dans un monde idéal dans une galaxie très, très lointaine, toutes ces bibliothèques qui tentent de résoudre ce problème de type fichier-à-mime ne feraient qu'implémenter Java.nio.fichier.le spi.FileTypeDetector , vous déposeriez le fichier jar de la bibliothèque d'implémentation préférée dans votre classpath et ce serait tout.
dans le monde réel, celui où vous avez besoin de TL,section DR, vous devriez trouver la bibliothèque avec la plupart des étoiles à côté de son nom et de l'utiliser. Pour ce cas particulier, je n'en ai pas besoin (encore ;) ).
C'est le moyen le plus simple que j'ai trouvé pour faire ceci:
byte[] byteArray = ...
InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));
String mimeType = URLConnection.guessContentTypeFromStream(is);
si vous travaillez sur linux OS ,il y a une ligne de commande file --mimetype
:
String mimetype(file){
//1. run cmd
Object cmd=Runtime.getRuntime().exec("file --mime-type "+file);
//2 get output of cmd , then
//3. parse mimetype
if(output){return output.split(":")[1].trim(); }
return "";
}
puis
mimetype("/home/nyapp.war") // 'application/zip'
mimetype("/var/www/ggg/au.mp3") // 'audio/mp3'
au printemps MultipartFile "151930920 de fichier";
org.springframework.Web.multipart.MultipartFile
file.getContentType();
après avoir essayé diverses autres bibliothèques, je me suis installé avec mime-util.
<groupId>eu.medsea.mimeutil</groupId>
<artifactId>mime-util</artifactId>
<version>2.1.3</version>
</dependency>
File file = new File("D:/test.tif");
MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
Collection<?> mimeTypes = MimeUtil.getMimeTypes(file);
System.out.println(mimeTypes);
public String getFileContentType(String fileName) {
String fileType = "Undetermined";
final File file = new File(fileName);
try
{
fileType = Files.probeContentType(file.toPath());
}
catch (IOException ioException)
{
System.out.println(
"ERROR: Unable to determine file type for " + fileName
+ " due to exception " + ioException);
}
return fileType;
}
vous pouvez le faire avec une seule ligne: MimetypesFileTypeMap().getContentType (nouveau fichier " filename.ext")) . Regardez le code de test complet (Java 7):
import java.io.File;
import javax.activation.MimetypesFileTypeMap;
public class MimeTest {
public static void main(String a[]){
System.out.println(new MimetypesFileTypeMap().getContentType(
new File("/path/filename.txt")));
}
}
ce code produit la sortie suivante: text / plain