2011-01-05 5 views
22

Domanda semplice: come posso ottenere il tipo MIME (o il tipo di contenuto) di un InputStream, senza salvare il file, per un file che un utente sta caricando sul mio servlet?Come posso ottenere il tipo MIME di un InputStream di un file che viene caricato?

+2

casi in cui è l'InputStream che viene? Se è solo un flusso di input generico con alcune serie di byte, sono "non tipizzati" e non si saprà senza leggere il contenuto stesso e determinare. Ma se stai ricevendo i byte da una connessione (diciamo) HTTP, ci sono le intestazioni della banda laterale che possono dirti quello che vuoi. –

+0

Proviene da file di upload dell'utente. – Trick

+0

Si potrebbe provare la libreria 'MimeUtils'. – herrtim

risposta

6

Dipende da dove si sta ricevendo il flusso di input. Se lo si ottiene da un servlet, è accessibile tramite l'oggetto HttpServerRequest che è un argomento di doPost. Se stai usando una specie di API di riposo come Jersey, la richiesta può essere iniettata usando @Context. Se si sta caricando il file tramite un socket, sarà responsabilità dell'utente specificare il tipo MIME come parte del protocollo in quanto non si erediteranno le intestazioni http.

1

È possibile controllare il Content-Typeheader field e dare un'occhiata allo extension of the filename utilizzato. Per tutto il resto, è necessario eseguire routine più complesse, come il controllo di Tika ecc.

1

È possibile semplicemente aggiungere tika-app-1.x.jar al classpath se non si utilizza la registrazione di slf4j ovunque altrimenti perché causerà una collisione. Se si utilizza tika per rilevare un inputstream deve essere contrassegnato come supportato. In caso contrario, la chiamata a tika cancellerà il flusso di input. Tuttavia, se si utilizza la libreria IO di apache per aggirare questo problema e basta trasformare l'InputStream in un file in memoria.

import org.apache.tika.*; 

Tike tika = new Tika(); 
InputStream in = null; 
FileOutputStream out = null; 
try{ 
    out = new FileOutputStream(c:/tmp.tmp); 
    IOUtils.copy(in, out); 
    String mimeType = tika.detect(out); 
}catch(Exception e){ 
    System.err.println(e); 
} finally { 
    if(null != in) 
     in.close(); 
    if(null != out) 
     out.close(); 
} 
9

ho scritto il mio rilevatore tipo di contenuto per un byte [] perché le librerie di cui sopra non erano adatti o non ho avuto accesso ad essi. Speriamo che questo aiuti qualcuno fuori.

// retrieve file as byte[] 
byte[] b = odHit.retrieve(""); 

// copy top 32 bytes and pass to the guessMimeType(byte[]) funciton 
byte[] topOfStream = new byte[32]; 
System.arraycopy(b, 0, topOfStream, 0, topOfStream.length); 
String mimeGuess = guessMimeType(topOfStream); 

...

private static String guessMimeType(byte[] topOfStream) { 

    String mimeType = null; 
    Properties magicmimes = new Properties(); 
    FileInputStream in = null; 

    // Read in the magicmimes.properties file (e.g. of file listed below) 
    try { 
     in = new FileInputStream("magicmimes.properties"); 
     magicmimes.load(in); 
     in.close(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    // loop over each file signature, if a match is found, return mime type 
    for (Enumeration keys = magicmimes.keys(); keys.hasMoreElements();) { 
     String key = (String) keys.nextElement(); 
     byte[] sample = new byte[key.length()]; 
     System.arraycopy(topOfStream, 0, sample, 0, sample.length); 
     if(key.equals(new String(sample))){ 
      mimeType = magicmimes.getProperty(key); 
      System.out.println("Mime Found! "+ mimeType); 
      break; 
     } else { 
      System.out.println("trying "+key+" == "+new String(sample)); 
     } 
    } 

    return mimeType; 
} 

magicmimes.properties esempio di file (non è sicuro queste firme sono corrette, ma hanno lavorato per i miei usi)

# SignatureKey     content/type 
\u0000\u201E\u00f1\u00d9  text/plain 
\u0025\u0050\u0044\u0046  application/pdf 
%PDF       application/pdf 
\u0042\u004d     image/bmp 
GIF8       image/gif 
\u0047\u0049\u0046\u0038  image/gif 
\u0049\u0049\u004D\u004D  image/tiff 
\u0089\u0050\u004e\u0047  image/png 
\u00ff\u00d8\u00ff\u00e0  image/jpg 
+4

Nota, che questo non funzionerà per PNG, ad esempio, il cui primo byte è 137.Considerando che il byte è firmato in Java (non può contenere valori maggiori di 128), viene convertito in -119. Quello che ho fatto è che ho letto InputStream sull'array int [4], usando il metodo readStream # read(), che restituisce i byte come input, in modo che non vengano convertiti. Grazie per la tua risposta, comunque! – jFrenetic

0

se si utilizza un JAX-RS servizio di riposo si può ottenere da MultipartBody.

@POST 
@Path("/<service_path>") 
@Consumes("multipart/form-data") 
public Response importShapeFile(final MultipartBody body) { 
    String filename = null; 
    String InputStream stream = null; 
    for (Attachment attachment : body.getAllAttachments()) 
    { 
     ContentDisposition disposition = attachment.getContentDisposition(); 
     if (disposition != null && PARAM_NAME.equals(disposition.getParameter("name"))) 
     { 
      filename = disposition.getParameter("filename"); 
      stream = attachment.getDataHandler().getInputStream(); 
      break; 
     } 
    } 

    // Read extension from filename to get the file's type and 
    // read the stream accordingly. 
} 

Dove PARAM_NAME è una stringa che rappresenta il nome del parametro che contiene il flusso di file.

-3

Penso che questo risolve anche problemi:

public String readIt(InputStream is) { 
    if (is != null) { 
      BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8); 

      StringBuilder sb = new StringBuilder(); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       sb.append(line).append("\n"); 
      } 
      is.close(); 
      return sb.toString(); 
    } 
    return "error: "; 
}   

Cosa reaturns? Ad esempio, per png: "♦ PNG \ n \ n ♦♦♦ .....", per xml:

Molto utile, non puoi provare string.contains() per verificare che cosa è