Come controllare un file caricato se si tratta di un’immagine o di un altro file?

Nella mia applicazione web ho un modulo di caricamento delle immagini. Voglio controllare il file caricato se si tratta di un file immagine o di qualsiasi altro file. Sto usando Java sul lato server.

L’immagine viene letta come BufferedImage in java e quindi la scrivo sul disco con ImageIO.write()

Come posso controllare BufferedImage , che si tratti di un’immagine o di qualcos’altro?

Eventuali suggerimenti o collegamenti sarebbero apprezzati.

    Presumo che tu stia eseguendo questo in un contesto servlet. Se è conveniente controllare il tipo di contenuto basandosi solo sull’estensione del file, quindi utilizzare ServletContext#getMimeType() per ottenere il tipo mime (tipo di contenuto). Basta controllare se inizia con image/ .

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

    I tipi mime predefiniti sono definiti nel web.xml del servlet container in questione. Ad esempio, Tomcat si trova in /conf/web.xml . Puoi estenderlo / sostituirlo nel /WEB-INF/web.xml della tua webapp come segue:

      svg image/svg+xml  

    Ma questo non ti impedisce di utenti che ti stanno prendendo in giro modificando l’estensione del file. Se vuoi coprire anche questo, allora puoi anche determinare il tipo mime basato sul contenuto del file reale . Se è conveniente verificare solo i tipi BMP, GIF, JPG o PNG (ma non TIF, PSD, SVG, ecc.), Puoi semplicemente ImageIO#read() direttamente a ImageIO#read() e verificare se non genera un’eccezione .

     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. } } 

    Ma se vuoi coprire più tipi di immagine, allora considera di usare una libreria di terze parti che fa tutto il lavoro sniffando le intestazioni dei file . Ad esempio JMimeMagic o Apache Tika che supportano sia BMP, GIF, JPG, PNG, TIF e PSD (ma non SVG). Apache Batik supporta SVG. Nell’esempio seguente viene utilizzato 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. } } 

    Se necessario, potresti usare combinazioni e superare l’una e l’altra.

    Detto questo, non è necessario necessariamente ImageIO#write() per salvare l’immagine caricata sul disco. Basta scrivere l’ InputStream ottenuto direttamente su un Path o su qualsiasi OutputStream come FileOutputStream il solito modo Java IO è più che sufficiente (vedere anche Modo consigliato per salvare i file caricati in un’applicazione servlet ):

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

    A meno che non ti piacerebbe raccogliere alcune informazioni sull’immagine come le sue dimensioni e / o voler manipolarle (ridimensionare / ridimensionare / ruotare / convertire / etc), ovviamente.

    Ho usato org.apache.commons.imaging.Imaging nel mio caso. Di seguito è riportato un esempio di codice per verificare se un’immagine è un’immagine jpeg o meno. Genera ImageReadException se il file caricato non è un’immagine.

      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 } 

    Questo è integrato nel JDK e richiede semplicemente uno streaming con supporto

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