webentwicklung-frage-antwort-db.com.de

Wie kann ich den MIME-Typ eines InputStreams einer Datei erhalten, die hochgeladen wird?

Einfache Frage: Wie kann ich für eine Datei, die ein Benutzer in mein Servlet lädt, den MIME-Typ (oder Inhaltstyp) einer InputStream erhalten, ohne die Datei zu speichern?

25
Trick

Es hängt davon ab, woher Sie den Eingabestrom beziehen. Wenn Sie es von einem Servlet erhalten, ist es über das HttpServerRequest-Objekt, das ein Argument von doPost ist, zugänglich. Wenn Sie eine Art Rest-API wie Jersey verwenden, kann die Anforderung mithilfe von @Context eingefügt werden. Wenn Sie die Datei über ein Socket hochladen, müssen Sie den MIME-Typ als Teil Ihres Protokolls angeben, da Sie die http-Header nicht erben.

6
LINEMAN78

Ich habe einen eigenen Inhaltstyp-Detektor für ein Byte [] geschrieben, weil die oben genannten Bibliotheken nicht geeignet waren oder ich keinen Zugriff darauf hatte. Hoffentlich hilft das jemandem. 

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

beispiel für die Datei "magicmimes.properties" (nicht sicher, ob diese Signaturen korrekt sind, aber sie funktionierten für meine Zwecke)

# 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

Laut Real Gagnons hervorragender Website wäre die bessere Lösung für Ihren Fall die Verwendung von Apache Tika .

7
Riduidel

Sie können das Content-TypeHeaderfeld überprüfen und sich die Erweiterung des Dateinamens ansehen. Für alles andere müssen Sie komplexere Routinen ausführen, z. B. das Prüfen mit Tikaetc.

1
b_erb

Sie können tika-app-1.x.jar einfach zu Ihrem Klassenpfad hinzufügen, solange Sie die slf4j-Protokollierung an keiner anderen Stelle verwenden, da dies zu einer Kollision führt. Wenn Sie tika verwenden, um einen Eingabestrom zu erkennen, muss er markiert werden. Andernfalls löscht der Aufruf von tika Ihren Eingabestrom. Wenn Sie jedoch die Apache IO - Bibliothek verwenden, um dies zu umgehen, müssen Sie InputStream einfach in eine Datei im Speicher verwandeln.

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

Wenn Sie einen JAX-RS-Rest-Service verwenden, können Sie ihn vom MultipartBody erhalten.

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

PARAM_NAME ist eine Zeichenfolge, die den Namen des Parameters angibt, der den Dateistream enthält.

0
crowmagnumb