2011-01-05 18 views
22

Pregunta simple: ¿cómo puedo obtener el tipo MIME (o tipo de contenido) de un InputStream, sin guardar el archivo, para un archivo que un usuario está cargando a mi servlet?¿Cómo puedo obtener el tipo MIME de un InputStream de un archivo que se está cargando?

+2

Dónde está viene el InputStream? Si se trata de un flujo de entrada genérico con algunas series de bytes, están "sin tipo" y no lo sabrá sin leer el contenido y determinarlo. Pero si obtiene los bytes de una (por ejemplo) conexión HTTP, hay encabezados de banda lateral que pueden indicarle lo que desea. –

+0

Viene de los archivos de carga del usuario. – Trick

+0

Puede probar la biblioteca 'MimeUtils'. – herrtim

Respuesta

6

Depende de donde se obtiene el flujo de entrada. Si lo está obteniendo de un servlet, entonces es accesible a través del objeto HttpServerRequest que es un argumento de doPost. Si está utilizando algún tipo de API de descanso como Jersey, la solicitud puede ser inyectada utilizando @Context. Si está cargando el archivo a través de un socket, será su responsabilidad especificar el tipo MIME como parte de su protocolo, ya que no heredará los encabezados http.

1

Puede consultar el Content-Typeheader field y echar un vistazo al extension of the filename utilizado. Para todo lo demás, debe ejecutar rutinas más complejas, como consultar por Tika, etc.

1

Puede agregar el tika-app-1.x.jar a su classpath siempre que no use el registro slf4j en cualquier lugar más porque causará una colisión. Si usas tika para detectar un flujo de entrada, tiene que ser marcado como compatible. De lo contrario, al llamar a tika se borrará tu flujo de entrada. Sin embargo, si utiliza la biblioteca apache IO para evitar esto y simplemente convierte el InputStream en un archivo en la 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

escribí mi propio detector de tipo de contenido para un byte [] porque las bibliotecas anterior no eran adecuados o que no tienen acceso a ellos. Espero que esto ayude a alguien a salir.

// 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 ejemplo de archivo (no estoy seguro estas firmas son correctas, pero trabajaron para mis usos)

# 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

Tenga en cuenta que esto no funcionará para PNG, por ejemplo, cuyo primer byte es 137.Considerando que el byte está firmado en Java (no puede contener valores mayores a 128), se convierte a -119. Lo que hice fue leer InputStream en la matriz int [4], usando el método InputStream # read(), que devuelve bytes como ints, para que no se conviertan. ¡Gracias por tu respuesta, de todos modos! – jFrenetic

0

si se utiliza un JAX-RS servicio de descanso puede obtenerlo desde 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. 
} 

Dónde PARAM_NAME es una cadena que representa el nombre del parámetro de la celebración de la secuencia de archivo.

-3

Creo que esto también resuelve un problema:

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: "; 
}   

Lo que reaturns? Por ejemplo, para png: "♦ PNG \ n \ n ♦♦♦ .....", por xml:

Muy útiles, Usted no puede intentar string.contains() para comprobar qué es lo

Cuestiones relacionadas