Подтвердить что ты не робот

Как я могу получить MIME-тип InputStream файла, который загружается?

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

Ответ 4

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

Ответ 5

Вы можете просто добавить tika-app-1.x.jar в свой путь к классам, если вы не используете запись slf4j нигде, потому что это вызовет столкновение. Если вы используете tika для обнаружения входного потока, он должен быть отмечен. В противном случае вызов tika приведет к стиранию входного потока. Однако, если вы используете библиотеку ввода-вывода apache, чтобы обойти это и просто превратите 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();
 }

Ответ 6

Если вы используете службу отдыха 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 type and
    // read the stream accordingly.
}

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

Ответ 7

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

    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(), чтобы проверить, что это такое