サーブレットでのイメージの受け取り
続いて、送信されたイメージ(BufferedIMageオブジェクト)をサーブレット側で受け取る処理saveImageToFileメソッドを考えてみましょう。
private void saveImageToFile(HttpServletRequest request) { ServletContext application = this.getServletContext(); String fpath = application.getRealPath("WEB-INF/" + imgpath); ServletInputStream input = null; try { input = request.getInputStream(); BufferedImage img = ImageIO.read(input); ImageIO.write(img,"jpeg",new File(fpath)); } catch (IOException ex) { ex.printStackTrace(); } finally { try { input.close(); } catch (Exception ex2) { ex2.printStackTrace(); } } }
ここでは、まずServletContextインスタンスを取得し、そこからgetRealPathで保存するファイルのフルパスを得ておきます。いわば、下準備です。
ServletContext application = this.getServletContext(); String fpath = application.getRealPath("WEB-INF/" + imgpath);
続いて、HttpServletRequestからServletInputStreamを取得します。このストリームから、送信されてきたイメージのデータが得られるわけです。
input = request.getInputStream();
後は、ImageIOを使ってイメージを読み込み、ファイルに出力するだけです。ImageIO.readでInputStreamからイメージを読み込み、これをImageIO.writeでファイルに書き出します。
BufferedImage img = ImageIO.read(input);
ImageIO.write(img,"jpeg",new File(fpath));
ImageIO.readは、このようにストリームからイメージをそのまま取り出すこともできるのです。これを利用すれば、送信されたBufferedImageをストリームから取り出すのは訳ありません。
サーブレットからアプレットへの送信
今度は、逆を行いましょう。サーブレットでファイルから読み込んだBufferedImageを送信しアプレットで受け取る、という処理です。といっても、もちろん勝手にサーブレットから送ったりするわけではなくて、アプレットからサーブレットに「イメージを送れ」と要求を出し、それに応じてサーブレットがデータを送信し、それをアプレットが受け取って表示するわけです。
まずは、アプレット側のイメージ読み込み処理loadImageメソッドから作成しましょう。
private void loadImage(ActionEvent ev){ ImageInputStream imgin = null; InputStream in = null; try { URL url = new URL(servpath); HttpURLConnection connect = (HttpURLConnection)url.openConnection(); connect.setDoInput(true); connect.setRequestMethod("GET"); in = connect.getInputStream(); imgin = ImageIO.createImageInputStream(in); BufferedImage im = ImageIO.read(imgin); panel.setDrawImage(im); } catch (Exception ex) { ex.printStackTrace(); } finally { try { imgin.close(); connect.disconnect(); } catch (Exception ex2) { ex2.printStackTrace(); } } }
イメージの送信の逆ですが、こちらの方が若干簡単になります。まず、読み込むイメージのURLと、HttpURLConnectionインスタンスの作成を行います。
URL url = new URL(servpath);
HttpURLConnection connect =
(HttpURLConnection)url.openConnection();
これは送信の場合と同じですから分かりますね。続いて、
connect.setDoInput(true); connect.setRequestMethod("GET");
そしてストリーム関係の作成です。既に先ほどImageIO.readを使ってreadする方法は学んでいますから、これをそのまま使うだけです。
imgin = ImageIO.createImageInputStream(in); BufferedImage im = ImageIO.read(imgin);
ImageIO.createImageInputStreamでImageInputStreamを作成し、これを利用してImageIO.readからイメージを読み込みます。後は、ImagePanelのsetDrawImageを呼び出して、受け取ったイメージを表示させるだけです。
サーブレットでのイメージの送信
では、イメージを送信しているサーブレット側の処理はどうなるでしょうか。loadImageFromFileメソッドとして定義する内容を作成しましょう。
public void loadImageFromFile(HttpServletResponse response){ ServletContext application = this.getServletContext(); String fpath = application.getRealPath("WEB-INF/" + imgpath); ServletOutputStream sos = null; try { response.setContentType("image/jpeg"); sos = response.getOutputStream(); BufferedImage img = ImageIO.read(new File(fpath)); ImageOutputStream ios = ImageIO.createImageOutputStream(sos); ImageIO.write(img,"JPEG",ios); } catch(IOException ex) { ex.printStackTrace(); } finally { try { sos.close(); } catch(IOException ex2) {} } }
先のsaveImageToFileと同様に、まずはServletContextと読み込むファイルのフルパスをgetRealPathで取得しておきます。そして送信するコンテンツの種類を設定します。
response.setContentType("image/jpeg");
ここではJPEGのイメージとして送信をしますので、setContentTypeで"image/jpeg"にしておきます。ここまでで下準備は完了です。
では、出力用のストリームを用意していきます。まずHttpServletResponseからOutputStreamを取得し、ImageIOを使ってImageOutputStreamを作成して、これにイメージを送信します。
sos = response.getOutputStream(); BufferedImage img = ImageIO.read(new File(fpath)); ImageOutputStream ios = ImageIO.createImageOutputStream(sos); ImageIO.write(img,"JPEG",ios);
ストリームを準備し、ImageIOでイメージ用のストリームを作って読み書きする、という基本的な流れは、読み込みも書き出しもほぼ同じです。この流れが分かれば、サーブレット側の処理はそう悩むことはないでしょう。
まとめ
アプレット/サーブレット間でイメージをやり取りするためには、アプレットとサーブレットのそれぞれの処理方法を頭に入れておく必要があります。注意するポイントを整理すると次のようになります。
- アプレットでは、
HttpURLConnectionの基本的な使い方を理解する。 - サーブレットでは、
HttpServletRequestまたはHttpServletResponseから入出力のストリームを取得し利用する。 - いずれの場合も、
ImageIOからイメージ用のストリームを用意し、同じくImageIOのread/writeでストリームにイメージを送受する。
ImageIOのおかげで、イメージ関係のストリームの作成や入出力などが実に簡単になっていることが実感できるでしょう。アプレットからサーブレットを利用できるようになれば、アプレットもいろいろと応用できるようになるはずです。フロントエンドとしてのアプレットを見直すきっかけとなれば幸いです。
