リクエストに応答したサーブレットが返すレスポンスは、HTMLのような文字データだけでなく、JPEG画像のようなバイナリデータも可能です。このTipsでは例としてJPEGデータを返す方法を紹介します。
サーブレットでは,レスポンスとしてHTMLのようなテキストデータを返す場合,javax.servlet.HttpServletResponse#getWriterメソッドを使ってPrinterWriterオブジェクトにテキストデータを書き出すか,対応するJSPにフォワードします。これら対し,レスポンスとしてバイナリデータを書き出す場合は,HttpServletResponse#getOutputStreamメソッドを使ってServletOutputStreamオブジェクトを取得して行います。
手順としては,HttpServletResponse#setContentTypeメソッドでコンテンツ形式を指定します。パラメータは,MIMEタイプを表す文字列で,JPEGデータであれば"images/hare.jpg"を指定します。バイナリデータの場合,データを書き込む際テキストデータのように文字エンコーディングに対する処理を行わないため,setContentTypeメソッドの呼び出しは,バイナリデータを書き込んだあとでもかまいません。
バイナリデータの書き出しは,データ型ごとに用意されたServletOutputStream#printおよびprintlnメソッド,writeメソッドを使います。printlnメソッドは,データを書き出したあとに改行文字を書き出します。次のリストは,/images/hare.jpgファイルを読み込み,そのままレスポンスとして返すものです。
リスト1 レスポンスとしてJPEGファイルを返す
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("image/jpeg");
ServletOutputStream out = res.getOutputStream();
String realPath = this.getServletContext().
getRealPath("/images/hare.jpg");
BufferedInputStream in = new BufferedInputStream(
new FileInputStream(realPath));
byte[] data = new byte[1024];
int len;
while ((len = in.read(data, 0, 1024)) != -1) {
out.write(data, 0, len);
}
in.close();
}
データの読み書き部分は,1バイト単位で読み書きすることも可能です。
リスト2 1バイト単位で読み書きする
int data;
while ((data = in.read()) != -1) {
out.write(data);
}
この場合でもレスポンスは正しく返るのですが,リスト2はリスト1に比べ読み書き時間がかかります。ファイルサイズが大きくなるほど,その違いは顕著です。このような場合は,1バイト単位の読み書きを行うべきではないでしょう。1回の読み込みサイズに関しては,読み込むバイナリデータのサイズやメモリー容量を十分に考慮して決めましょう。
「JAVA Developer」より毎週役立つJava Tipsを配信中。ほかにも参考になるTipsは、JAVA Developerサイトのバックナンバーから探すことが可能です。
Copyright(C) 2010 SOFTBANK Creative Inc. All Right Reserved.