Как я могу получить MIME-тип InputStream загружаемого файла? - PullRequest
25 голосов
/ 05 января 2011

Простой вопрос: как я могу получить MIME-тип (или тип содержимого) InputStream, без сохранения файла, для файла, который пользователь загружает в мой сервлет?

Ответы [ 7 ]

10 голосов
/ 15 марта 2014

Я написал свой собственный детектор типа контента для байта [], потому что библиотеки выше не подходили или у меня не было доступа к ним.Надеюсь, это поможет кому-то.

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

пример файла 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
7 голосов
/ 05 января 2011

По мнению отличного сайта Real Gagnon , лучшим решением для вашего случая будет использование Apache Tika .

6 голосов
/ 05 января 2011

Это зависит от того, откуда вы получаете входной поток. Если вы получаете его из сервлета, то он доступен через объект HttpServerRequest, который является аргументом doPost. Если вы используете какой-то API отдыха, например, Джерси, запрос может быть введен с помощью @Context. Если вы загружаете файл через сокет, вы будете обязаны указать тип MIME как часть вашего протокола, поскольку вы не будете наследовать заголовки http.

1 голос
/ 30 сентября 2013

Вы можете просто добавить tika-app-1.x.jar в ваш путь к классу, если вы не используете логи slf4j где-либо еще, потому что это вызовет конфликт.Если вы используете тика для обнаружения входного потока, он должен быть помечен как поддерживаемый.В противном случае, вызов тика сотрет ваш поток ввода.Однако, если вы используете библиотеку Apache IO, чтобы обойти это, и просто превратите InputStream в файл в памяти.

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 голос
/ 05 января 2011

Вы можете проверить поле заголовка Content-Type и взглянуть на расширение имени файла .Для всего остального вам нужно запускать более сложные процедуры, такие как проверка по Tika и т. Д.

0 голосов
/ 02 января 2016

Я думаю, что это решает проблему:

    public String readIt(InputStream is) {
    if (is != null) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8);

            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
            is.close();
            return sb.toString();
    }
    return "error: ";
}        

Что это возвращает?Например, для png: «♦ PNG \ n \ n ♦♦♦ .....», для xml:

Довольно полезно, вы не можете попробовать string.contains (), чтобы проверить, что это такое

0 голосов
/ 30 октября 2014

Если вы используете службу отдыха JAX-RS, вы можете получить ее из 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.
}

Где PARAM_NAME - строка, представляющая имя параметра, содержащего поток файла.

...