Domanda

Mi stavo solo chiedendo come fa la maggior parte delle persone a recuperare un tipo MIME da un file in Java?Finora ho provato due util: JMimeMagic & Mime-Util.

Il primo mi ha dato eccezioni di memoria, il secondo non chiude correttamente i suoi flussi.Mi stavo solo chiedendo se qualcun altro avesse un metodo/libreria che utilizzava e funzionava correttamente?

È stato utile?

Soluzione

In Java 7 ora puoi semplicemente usare Files.probeContentType(path).

Altri suggerimenti

Purtroppo,

mimeType = file.toURL().openConnection().getContentType();

non funziona, poiché questo utilizzo dell'URL lascia il file bloccato, rendendolo, ad esempio, incancellabile.

Tuttavia, hai questo:

mimeType= URLConnection.guessContentTypeFromName(file.getName());

e anche il seguente, che ha il vantaggio di andare oltre il mero utilizzo dell'estensione del file, e di dare una sbirciatina al contenuto

InputStream is = new BufferedInputStream(new FileInputStream(file));
mimeType = URLConnection.guessContentTypeFromStream(is);
 //...close stream

Tuttavia, come suggerito dal commento sopra, la tabella incorporata dei tipi MIME è piuttosto limitata e non include, ad esempio, MSWord e PDF.Quindi, se vuoi generalizzare, dovrai andare oltre le librerie integrate, utilizzando, ad esempio, Mime-Util (che è un'ottima libreria, che utilizza sia l'estensione del file che il contenuto).

L'API JAF fa parte di JDK 6.Guarda a javax.activation pacchetto.

Le lezioni più interessanti lo sono javax.activation.MimeType - un titolare effettivo del tipo MIME - e javax.activation.MimetypesFileTypeMap - classe la cui istanza può risolvere il tipo MIME come String per un file:

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

Con Apache Tika ti serve solo tre righe di codice:

File file = new File("/path/to/file");
Tika tika = new Tika();
System.out.println(tika.detect(file));

Se hai una console fantastica, incolla ed esegui questo codice per giocarci:

@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)

Tieni presente che le sue API sono ricche, può analizzare "qualsiasi cosa".A partire da tika-core 1.14, hai:

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)

Vedere gli apidoc per maggiori informazioni.

Apache Tika offerte dentro tika-core un rilevamento del tipo MIME basato su marcatori magici nel prefisso dello stream. tika-core non recupera altre dipendenze, il che lo rende leggero come quello attualmente non mantenuto Utilità di rilevamento del tipo MIME.

Esempio di codice semplice (Java 7), utilizzando le variabili theInputStream E 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();
}

Tieni presente che MediaType.detect(...) non può essere utilizzato direttamente (TIKA-1120).Ulteriori suggerimenti sono forniti a https://tika.apache.org/0.10/detection.html.

Se sei uno sviluppatore Android, puoi utilizzare una classe di utilità android.webkit.MimeTypeMap che mappa i tipi MIME sulle estensioni dei file e viceversa.

Il seguente snippet di codice può aiutarti.

private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}

Da roseindia:

FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");

Se sei bloccato con Java 5-6 quindi questa classe di utilità da prodotto open source Servoy.

Hai solo bisogno di questa funzione

public static String getContentType(byte[] data, String name)

Esamina i primi byte del contenuto e restituisce i tipi di contenuto in base a tale contenuto e non in base all'estensione del file.

Mi stavo solo chiedendo come fa la maggior parte delle persone a recuperare un tipo MIME da un file in Java?

Ho pubblicato il mio SimpleMagic Pacchetto Java che consente la determinazione del tipo di contenuto (tipo MIME) da file e array di byte.È progettato per leggere ed eseguire i file magici dei comandi Unix file(1) che fanno parte della maggior parte delle configurazioni del sistema operativo ~Unix.

Ho provato Apache Tika ma lo è Enorme con tonnellate di dipendenze, URLConnection non utilizza i byte dei file e MimetypesFileTypeMap guarda anche solo i nomi dei file.

Con SimpleMagic puoi fare qualcosa come:

// 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();
}

Per contribuire con i miei 5 centesimi:

TL, DR

Io uso Tipi MIMEFileTypeMap e aggiungi qualsiasi mime che non è presente e ne ho specificamente bisogno, nel file mime.types.

E ora, la lunga lettura:

Prima di tutto, l'elenco dei tipi MIME è Enorme, Vedere qui: https://www.iana.org/assignments/media-types/media-types.xhtml

Mi piace utilizzare prima le funzionalità standard fornite da JDK e, se non funziona, vado a cercare qualcos'altro.

Determina il tipo di file dall'estensione del file

Dalla versione 1.6, Java ha MimetypesFileTypeMap, come indicato in una delle risposte sopra, ed è il modo più semplice per determinare il tipo MIME:

new MimetypesFileTypeMap().getContentType( fileName );

Nella sua implementazione vanilla questo non fa molto (cioèfunziona per .html ma non per .png).Tuttavia, è semplicissimo aggiungere qualsiasi tipo di contenuto di cui potresti aver bisogno:

  1. Crea un file denominato "mime.types" nella cartella META-INF del tuo progetto
  2. Aggiungi una riga per ogni tipo MIME di cui hai bisogno e l'implementazione predefinita non lo fornisce (ci sono centinaia di tipi MIME e l'elenco cresce col passare del tempo).

Voci di esempio per file png e js sarebbero:

image/png png PNG
application/javascript js

Per il formato file mime.types, vedere maggiori dettagli qui: https://docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.html

Determinare il tipo di file dal contenuto del file

Dalla versione 1.7, Java ha java.nio.file.spi.FileTypeDetector, che definisce un'API standard per determinare un tipo di file in modo specifico di implementazione.

Per recuperare il tipo MIME per un file, dovresti semplicemente usare File e fai questo nel tuo codice:

Files.probeContentType(Paths.get("either file name or full path goes here"));

La definizione API prevede funzionalità che supportano la determinazione del tipo MIME del file dal nome del file o dal contenuto del file (byte magici).È per questo sondaContenutoType() Il metodo lancia IOException, nel caso in cui un'implementazione di questa API utilizzi il percorso fornito per provare effettivamente ad aprire il file ad essa associato.

Ancora una volta, vaniglia implementazione di questo (quello fornito con JDK) lascia molto a desiderare.

In qualche mondo ideale in una galassia lontana lontana, tutte queste librerie che tentano di risolvere questo problema di tipo file-mime implementerebbero semplicemente java.nio.file.spi.FileTypeDetector, dovresti inserire il file jar della libreria di implementazione preferita nel tuo classpath e basta.

Nel mondo reale, quello in cui hai bisogno della sezione TL, DR, dovresti trovare la libreria con il maggior numero di stelle accanto al suo nome e usarla.Per questo caso particolare, non ne ho bisogno (ancora ;) ).

Ho provato diversi modi per farlo, inclusi i primi indicati da @Joshua Fox.Ma alcuni non riconoscono i tipi MIME frequenti come per i file PDF, e altri non potrebbero essere affidabili con file falsi (ho provato con un file RAR con estensione modificata in TIF).La soluzione che ho trovato, come detto anche da @Joshua Fox in modo superficiale, è usare MimeUtil2, come questo:

MimeUtil2 mimeUtil = new MimeUtil2();
mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();

È preferibile utilizzare la convalida a due livelli per il caricamento dei file.

Per prima cosa puoi verificare il mimeType e convalidarlo.

In secondo luogo dovresti cercare di convertire i primi 4 byte del tuo file in esadecimale e poi confrontarlo con i numeri magici.Quindi sarà un modo davvero sicuro per verificare la convalida dei file.

in primavera File multiparte file;

org.springframework.web.multipart.MultipartFile

file.getContentType();

Questo è il modo più semplice che ho trovato per farlo:

byte[] byteArray = ...
InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));
String mimeType = URLConnection.guessContentTypeFromStream(is);

se lavori su sistema operativo Linux, c'è una riga di comando 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 "";
}

Poi

mimetype("/home/nyapp.war") //  'application/zip'

mimetype("/var/www/ggg/au.mp3") //  'audio/mp3'

Dopo aver provato varie altre librerie ho optato per 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;
}

Puoi farlo con una sola riga: MimetypesFileTypeMap().getContentType(new File("filename.ext")).Guarda il codice di test completo (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")));
    }
}

Questo codice produce il seguente output: testo/semplice

File file = new File(PropertiesReader.FILE_PATH);
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file);
URLConnection uconnection = file.toURL().openConnection();
mimeType = uconnection.getContentType();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top