Простой вопрос: как я могу получить тип MIME (или тип контента) InputStream
без сохранения файла для файла, который пользователь загружает на свой сервлет?
Как я могу получить MIME-тип InputStream файла, который загружается?
Ответ 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
Ответ 3
Согласно Real Gagnon отличный сайт, лучшим решением для вашего дела будет использование Apache Tika.
Ответ 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(), чтобы проверить, что это такое