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

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

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

我为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); 

 private static String guessMimeType(byte[] topOfStream) { String mimeType = null; Properties magicmimes = new Properties(); FileInputStream in = null; // Read in the magicmimes.properties file (eg 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 

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

您可以检查Content-Type 标头字段 ,并查看所用文件名的扩展名 。 对于其他一切,你必须运行更复杂的例程,比如Tika等的检查。

只要不在其他地方使用slf4j日志记录,就可以将tika-app-1.x.jar添加到类路径中,因为它会导致冲突。 如果使用tika检测输入流,则必须标记支持。 否则,调用tika将清除输入流。 但是,如果您使用apache IO库来解决此问题,只需将InputStream转换为内存中的File即可。

 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(); } 

如果使用JAX-RSrest服务,您可以从MultipartBody获取它。

 @POST @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是表示保存文件流的参数名称的字符串。

我认为这解决了问题:

  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()来检查它是什么