如何获取正在上载的文件的InputStream的MIME类型?

Tri*_*ick 25 java servlets inputstream mime-types

简单的问题:如何在InputStream不保存文件的情况下获取用户上传到我的servlet的文件的MIME类型(或内容类型)?

Kit*_*Kit 11

我为byte []编写了自己的内容类型检测器,因为上面的库不合适或者我没有访问它们.希望这有助于某人.

// 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);
Run Code Online (Sandbox Code Playgroud)

...

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;
}
Run Code Online (Sandbox Code Playgroud)

magicmimes.properties文件示例(不确定这些签名是否正确,但它们适用于我的用途)

# 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
Run Code Online (Sandbox Code Playgroud)

  • 注意,这对PNG不起作用,例如,其第一个字节是137.考虑到字节是用Java签名的(不能保存大于128的值),它会转换为-119.我所做的是使用InputStream#read()方法将InputStream读入int [4]数组,该方法将字节作为整数返回,因此它们不会被转换.无论如何,谢谢你的回答! (5认同)

Rid*_*del 8

根据Real Gagnon的优秀网站,针对您的案例的更好解决方案是使用Apache Tika.

  • 我看了Tika,但有20个依赖...需要18MB.我会再考虑一下...... (6认同)

LIN*_*N78 6

这取决于您从哪里获取输入流.如果从servlet获取它,则可以通过作为doPost参数的HttpServerRequest对象访问它.如果您使用某种类型的休眠API,如Jersey,则可以使用@Context注入请求.如果您通过套接字上传文件,则您有责任将MIME类型指定为协议的一部分,因为您不会继承http标头.