2010-11-12 24 views
22

En mi aplicación web tengo un módulo de carga de imágenes. Quiero verificar el archivo cargado, ya sea un archivo de imagen o cualquier otro archivo. Estoy usando Java en el servidor.¿Cómo verificar un archivo cargado ya sea una imagen u otro archivo?

La imagen se lee como BufferedImage en Java y luego escribo en el disco con ImageIO.write()

¿Cómo voy a comprobar el BufferedImage, si es realmente una imagen o algo más?

Cualquier sugerencia o enlace sería apreciado.

+0

Su mejor apuesta es mirar a la extensión del archivo, no existe un método 100% para determinar si un archivo es una imagen o no –

Respuesta

85

Supongo que está ejecutando esto en un contexto de servlet. Si es asequible verificar el tipo de contenido basándose solo en la extensión del archivo, entonces use ServletContext#getMimeType() para obtener el tipo mime (tipo de contenido). Simplemente verifique si comienza con image/.

String fileName = uploadedFile.getFileName(); 
String mimeType = getServletContext().getMimeType(fileName); 
if (mimeType.startsWith("image/")) { 
    // It's an image. 
} 

los tipos MIME por defecto se definied en el web.xml del servletcontainer en cuestión. En, por ejemplo, Tomcat, está ubicado en /conf/web.xml. Se puede extender/anularlo en el /WEB-INF/web.xml de la aplicación web de la siguiente manera:

<mime-mapping> 
    <extension>svg</extension> 
    <mime-type>image/svg+xml</mime-type> 
</mime-mapping> 

Pero esto no le impide a los usuarios que le están engañando al cambiar la extensión de archivo. Si desea cubrir esto también, también puede determinar el tipo de mime basado en el contenido del archivo real. Si es asequible comprobar solo los tipos BMP, GIF, JPG o PNG (pero no TIF, PSD, SVG, etc.), puede simplemente alimentarlo directamente al ImageIO#read() y comprobar si no arroja una excepción.

try (InputStream input = uploadedFile.getInputStream()) { 
    try { 
     ImageIO.read(input).toString(); 
     // It's an image (only BMP, GIF, JPG and PNG are recognized). 
    } catch (Exception e) { 
     // It's not an image. 
    } 
} 

Pero si desea cubrir más tipos de imágenes, así, a continuación, considere el uso de una biblioteca de 3 ª parte, que hace todo el trabajo por oler el file headers. Por ejemplo, JMimeMagic o Apache Tika que admiten tanto BMP, GIF, JPG, PNG, TIF y PSD (pero no SVG). Apache Batik es compatible con SVG. A continuación utiliza JMimeMagic ejemplo:

try (InputStream input = uploadedFile.getInputStream()) { 
    String mimeType = Magic.getMagicMatch(input, false).getMimeType(); 
    if (mimeType.startsWith("image/")) { 
     // It's an image. 
    } else { 
     // It's not an image. 
    } 
} 

que podría si las combinaciones de uso necesario y pesar más que el uno y el otro.

Dicho esto, no necesita necesariamente ImageIO#write() para guardar la imagen cargada en el disco. Sólo escribir el InputStream obtenido directamente a un Path o cualquier OutputStream como FileOutputStream la manera habitual de Java IO es más que suficiente (véase también Recommended way to save uploaded files in a servlet application):

try (InputStream input = uploadedFile.getInputStream()) { 
    Files.copy(input, new File(uploadFolder, fileName).toPath()); 
} 

A menos que desea obtener alguna información de la imagen al igual que sus dimensiones y/o quiero manipularlo (recortar/cambiar tamaño/rotar/convertir/etc) por supuesto.

+2

Respuesta muy completa, que abarca todos los aspectos. Buen trabajo ... – Cahit

+0

Probé ImageIO.read (entrada); pero no arroja ninguna excepción cuando el archivo no es una imagen. –

+3

ImageIO.read (entrada); no arroja ninguna excepción si el archivo no es una imagen, sino que simplemente devuelve nulo. –

2

He usado org.apache.commons.imaging.Imaging en mi caso. A continuación se muestra una muestra de código para verificar si una imagen es una imagen JPEG o no. Lanza ImageReadException si el archivo cargado no es una imagen.

try { 
     //image is InputStream 
     byte[] byteArray = IOUtils.toByteArray(image); 
     ImageFormat mimeType = Imaging.guessFormat(byteArray); 
     if (mimeType == ImageFormats.JPEG) { 
      return; 
     } else { 
      // handle image of different format. Ex: PNG 
     } 
    } catch (ImageReadException e) { 
     //not an image 
    } 
+1

Aún - a partir de junio de 2017, la lib no tiene una versión estable y solo instantáneas. Podría ser peligroso usarlo en prod – George

1

Este está integrado en el JDK y simplemente requiere una corriente con soporte para

byte[] data = ; 
InputStream is = new BufferedInputStream(new ByteArrayInputStream(data)); 
String mimeType = URLConnection.guessContentTypeFromStream(is); 
//...close stream 
Cuestiones relacionadas