2011-01-05 16 views
22

簡単な質問:ユーザーが自分のサーブレットにアップロードしているファイルに対して、ファイルを保存せずにInputStreamのMIMEタイプ(またはコンテンツタイプ)を取得するにはどうすればよいですか?アップロードされているファイルのInputStreamのMIMEタイプを取得するにはどうすればよいですか?

+2

であるかどうか確認しますInputStreamはどこから来ますか?一連のバイトを含む汎用入力ストリームの場合、それらは「型指定されていない」ため、コンテンツ自体を読んだり決定したりすることはありません。しかし、HTTP接続からバイトを取得している場合は、サイドバンドヘッダーがあります。 –

+0

ファイルのアップロード中です。 – Trick

+0

'MimeUtils'ライブラリを試すことができます。 – herrtim

答えて

6

入力ストリームをどこから取得しているかによって異なります。サーブレットから取得している場合は、doPostの引数であるHttpServerRequestオブジェクトを通じてアクセス可能です。あなたがJerseyのような何らかの種類の残りのAPIを使用しているなら、@Contextを使ってリクエストを注入することができます。ソケット経由でファイルをアップロードする場合は、httpヘッダーを継承しないように、プロトコルの一部としてMIMEタイプを指定する責任があります。

1

Content-Typeheader fieldを確認して、extension of the filenameをご覧ください。それ以外の場合は、Tikaなどのようなより複雑なルーチンを実行する必要があります。

1

どこでも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(); 
} 
9

上記のライブラリは適していなかったか、私はそれらへのアクセスを持っていなかったので、私は[]バイトのために自分のコンテンツタイプの検出器を書きました。うまくいけば、これは誰かを助けてくれます

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

たとえば、最初のバイトが137のPNGでは、これは機能しません。バイトがJavaで署名されていると考えると(128より大きい値を保持できない)、-119に変換されます。私がしたことは、int型のバイトをint型として返すInputStream#read()メソッドを使って、int型の配列[4]に読み込まれて変換されないことです。とにかくあなたの答えをありがとう! – jFrenetic

0

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は、ファイルストリームを保持するパラメータの名前を表す文字列です。それはreaturns何

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: "; 
}   

:私はこれを考える

-3

も問題を解決しますか?たとえば、PNGのために: "♦PNG \ N \ N♦♦♦....." は、XMLのため:

かなり便利、あなたは(string.containsを試してみてくださいカント)それは

関連する問題