web-dev-qa-db-fra.com

Comment obtenir le type MIME d'un InputStream d'un fichier en cours de téléchargement?

Question simple: comment obtenir le type MIME (ou le type de contenu) d'une InputStream sans enregistrer de fichier pour un fichier téléchargé par un utilisateur sur mon servlet?

25
Trick

Cela dépend d'où vous obtenez le flux d'entrée. Si vous l'obtenez à partir d'un servlet, il est accessible via l'objet HttpServerRequest qui est un argument de doPost. Si vous utilisez une sorte d'API restante telle que Jersey, la requête peut être injectée à l'aide de @Context. Si vous téléchargez le fichier via un socket, il vous incombe de spécifier le type MIME dans le cadre de votre protocole car vous n'hériterez pas des en-têtes http.

6
LINEMAN78

J'ai écrit mon propre détecteur de type de contenu pour un octet [] parce que les bibliothèques ci-dessus n'étaient pas adaptées ou que je n'y avais pas accès. Espérons que cela aide quelqu'un. 

// 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;
}

exemple de fichier magicmimes.properties (pas sûr que ces signatures soient correctes, mais elles ont fonctionné pour mes utilisations)

# 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
9
Kit

Selon L’excellent site de Real Gagnon , la meilleure solution pour votre cas serait d’utiliser Apache Tika .

7
Riduidel

Vous pouvez vérifier le champ d'en-tête Content-Type et consulter l'extension du nom de fichier used. Pour tout le reste, vous devez exécuter des routines plus complexes, telles que la vérification par Tikaetc.

1
b_erb

Vous pouvez simplement ajouter le fichier tika-app-1.x.jar à votre chemin d'accès aux classes tant que vous n'utilisez pas la journalisation slf4j ailleurs, car cela provoquerait une collision. Si vous utilisez tika pour détecter un flux d'entrée, celui-ci doit être pris en charge. Sinon, appeler tika effacera votre flux d'entrée. Cependant, si vous utilisez la bibliothèque Apache IO pour contourner ce problème et que vous ne faites que transformer InputStream en fichier en mémoire.

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();
 }
1
kslote1

Si vous utilisez un service de repos JAX-RS, vous pouvez l'obtenir auprès du 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.
}

Où PARAM_NAME est une chaîne représentant le nom du paramètre contenant le flux de fichiers.

0
crowmagnumb