Solución:
Supongo que está ejecutando esto en un contexto de servlet. Si es asequible comprobar el tipo de contenido basándose únicamente en la extensión del archivo, utilice ServletContext#getMimeType()
para obtener el tipo de mímica (tipo de contenido). Solo verifica si comienza con image/
.
String fileName = uploadedFile.getFileName();
String mimeType = getServletContext().getMimeType(fileName);
if (mimeType.startsWith("image/")) {
// It's an image.
}
Los tipos de mimo predeterminados se definen en el web.xml
del contenedor de servlet en cuestión. En, por ejemplo, Tomcat, se encuentra en /conf/web.xml
. Puede extenderlo / anularlo en el /WEB-INF/web.xml
de su aplicación web de la siguiente manera:
<mime-mapping>
<extension>svg</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
Pero esto no evita que los usuarios lo engañen cambiando la extensión del archivo. Si desea cubrir esto también, también puede determinar el tipo de mímica en función de la real contenido del archivo. Si es asequible verificar solo los tipos BMP, GIF, JPG o PNG (pero no TIF, PSD, SVG, etc.), entonces puede enviarlo directamente a ImageIO#read()
y compruebe si no lanza 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 también desea cubrir más tipos de imágenes, considere usar una biblioteca de terceros que haga todo el trabajo olfateando los encabezados de los archivos. Por ejemplo, JMimeMagic o Apache Tika, que admiten BMP, GIF, JPG, PNG, TIF y PSD (pero no SVG). Apache Batik admite SVG. El siguiente ejemplo usa JMimeMagic:
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.
}
}
Si es necesario, podría usar combinaciones y superar a una y otra.
Dicho esto, no necesariamente necesitas ImageIO#write()
para guardar la imagen cargada en el disco. Solo escribiendo el obtenido InputStream
directamente a un Path
o cualquier OutputStream
igual que FileOutputStream
la forma habitual de Java IO es más que suficiente (consulte también Forma recomendada de guardar archivos cargados en una aplicación de servlet):
try (InputStream input = uploadedFile.getInputStream()) {
Files.copy(input, new File(uploadFolder, fileName).toPath());
}
A menos que desee recopilar información de la imagen como sus dimensiones y / o desee manipularla (recortar / cambiar el tamaño / rotar / convertir / etc.) por supuesto.
Usé org.apache.commons.imaging.Imaging en mi caso. A continuación se muestra un fragmento de código de muestra 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
}
Esto está integrado en el JDK y simplemente requiere una transmisión con soporte para
byte[] data = ;
InputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
String mimeType = URLConnection.guessContentTypeFromStream(is);
//...close stream