O que venho apresentar não se trata de uma dúvida.
Infelizmente sou obrigado a dizer que o método de validação do arquivo de upload apresentado aqui pode ser burlado. É possível, por exemplo, passar o mesmo arquivo de script com o prefixo 'GIF8' como primeiros caracteres (com ou sem a extensão .gif) e o método guessContentTypeFromStream vai retornar 'image/gif'. O exemplo abaixo demonstra isso.
import java.net.URLConnection;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
InputStream fakeGif = new ByteArrayInputStream(
"GIF8 <% some Java source could go here %>".getBytes());
String result = URLConnection.guessContentTypeFromStream(fakeGif);
System.out.println(result);
}
}
Da mesma forma, não é bom confiar no resultado deste método para validar outros tipos de arquivo cuja assinatura pode ser simulada usando texto puro, tal como .pdf, .psd e mesmo .mp3 na versão mais recente (que não são reconhecidos pelo método usado. Ref: https://en.wikipedia.org/wiki/List_of_file_signatures). Alias, o código implementado também vai permitir guardar e apresentar como se fosse uma imagem alguns arquivos de som e executáveis Java, por exemplo, o que também não me parece um comportamento legal.
A única forma 100% garantida de validar que temos uma imagem é tentando carregar a imagem, por exemplo, usando o método javax.imageio.ImageIO.read(). Caso o conteúdo da imagem não consiga ser carregado como uma imagem válida por algum dos formatos suportados, o método irá retornar null
. Para testar, acrescente as seguintes duas linhas ao final do exemplo acima:
BufferedImage image = ImageIO.read(fakeGif);
System.out.println(image);
O mesmo deveria ser feito caso a aplicação esteja esperando outros tipos de arquivo como de áudio, vídeo, ou mesmo documentos como PDF ou DOC, mas nem todos os formatos tem alguma implementação que consiga ler (e consequentemente validar) o conteúdo da stream.