こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

サーブレットからIMGタグへ画像が送れない

Apache1.3.26とTomcat4.0.6でjava1.4でIEに画像を表示するシステムを開発しています。

Tableタグで構成した表内に、サーブレットをリンク先としたIMGタグを3つ記述してあります。

  <tr><td>
    <img src='../servlet?param='aa''></a>
  </td><tr/><tr><td>
    <img src='../servlet?param='bb''></a>
  </td><tr/><tr><td>
    <img src='../servlet?param='cc''></a>
  </td><tr/>

このタグ内に記述しているサーブレットでは、DBより取得したパスを元にJpegファイルを
読込み、レスポンスに渡しています。

  response.setContentType("image/pjpeg");
  response.addHeader("Content-Disposition","inline; filename=" + fileName);
  InputStream in = null;
  OutputStream out = null;
  try {
    in = new FileInputStream(ImagePath);
    out = response.getOutputStream();
    int b;
    while ((b = in.read()) != -1) {
      out.write(b);
      break ;
    }
  } finally {
    if (in != null) {
      in.close();
    }
    if (out != null) {
      out.flush();
      out.close();
    }
  }

IEにこのHTMLを表示させると、ほとんどの場合はJpeg画像が表示されるのですが、
まれに表示されずに×印が出てしまうことがあります。
右クリックメニューより「画像の表示」を行うと表示されますが、ページを表示した際に表示されていないと使えるシステムとなりません。

何が原因なのかわからず、対処のしようがない状態です。
どなたか原因、対処方法についてご教授いただけないでしょうか?

投稿日時 - 2005-05-17 22:22:24

QNo.1393931

すぐに回答ほしいです

質問者が選んだベストアンサー

 こんばんは、#1です。

 こんなページを見つけました。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=12834&forum=12

 このページの

>java.net.SocketException: Software caused connection abort: socket write error
>at java.net.SocketOutputStream.socketWrite0(Native Method)

 この記述から件の例外はSocketOutputStream.socketWrite0発生しているのではないかと想像してみました。
 もしそうなら、例外の発生源は、

for(int i=0 ; i< 10 ; i++ ){
  try {
    out.write(b); ←ここ
    break ;
  }catch(IOException e){
    if( i == 9 ){
      throw e;
    }
  }
}

 のような気がします。

 SocketOutputStream.socketWrite0がネイティブメソッドであることから、プログラミングのミスによる原因というより、OSとか外部的な原因で接続が切れてしまっているのではないかと思います。

 OSやネットワークの設定とかその辺にも目を配ったほうがいいのではないでしょうか?

参考URL:http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=12834&forum=12

投稿日時 - 2005-05-18 20:49:33

お礼

再度の回答、ありがとうございます。

参考URL拝見しました。
ApacheとTomcatを連携させるとおかしなことになる事があるのですね。
プログラミングでは直せないとすると、どう対処すると良いのでしょうか?
どうにも手詰まりですね。
ApacheやTomcatの設定をいじると直るのだろうか……。

あ、あと、画像ファイルの読込みに BufferedInputStream を使うようにしたところ、
目に見えて早く表示されるようになりました。
問題を解決するには至りませんでしたが、これはこれで素晴らしい改善となりました。
重ねて御礼申し上げます。

投稿日時 - 2005-05-20 10:53:47

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

>java.net.SocketException: Software caused connection abort: socket write error
を見る限り、ブラウザから接続が切られていますね…。

>サーブレットとの通信が3つ同時に行われる事になると思います。この辺、何か関係してくるのでしょうか?
サーブレットのインスタンスは1つですが、スレッドは別なので、その辺に注意してあれば大丈夫なはずです。


…以下はもしかしたら関係ないかもしれませんが…
以前、ブラウザでクライアントにある沢山の画像を読み込むときに、A画面で「表示はしないけど」画像を読み込んでおいて、A画面の次のB画面で「A画面で読み込んでおいた」画像を表示するということをやっていました。
(実際にB画面が読み込むのはキャッシュからだと思われますが…)

前の仕事で別チームがやっていたことなのでもしかしたら今回の件とは関係ないかもしれませんが…
何かのヒントになれば幸いです。

投稿日時 - 2005-05-18 12:01:26

お礼

回答ありがとうございます。

>ブラウザから接続が切られていますね…。

なるほど。それでは画像が表示されないのも道理ですね。
しかし、残念ながら接続が切れてしまう原因に心当たりがありません。
SocketExceptionなどで検索していましたが、参考になりそうなものを見つけることもできませんでした。

切れてしまう原因としてどんなものがあるのでしょうか?
ご教授いただけないでしょうか。

>サーブレットのインスタンスは1つですが、スレッドは別なので、
>その辺に注意してあれば大丈夫なはずです。

スレッド間でデータを共有してしまうような処理が無ければ問題ないということですね。

>以前、ブラウザでクライアントにある沢山の画像を読み込むときに、
>A画面で「表示はしないけど」画像を読み込んでおいて、
>A画面の次のB画面で「A画面で読み込んでおいた」画像を
>表示するということをやっていました。

A画面に見えないようにIMGタグを記述しておくなどしているのでしょうか。
しかし、今回においては、問題発生がB画面からA画面に移るだけのような気もします(^^;;

投稿日時 - 2005-05-18 19:48:06

ANo.1

 こんにちは。

 私はサーブレットはさっぱりなので、アドバイスするのはおこがましいのですが、ちょっと気づいた点だけ。

1.breakが変なところにある。

while ((b = in.read()) != -1) {
  out.write(b);
  break ;
}

 これだと、すぐにループを出てしまってwhileの意味がないですよね。
 実際はほとんどの場合はjpegファイルが送ることができるとのことなので、多分、投稿するときの記述ミスだと思いますが、一応、指摘しておきます。
(投稿時の記述ミスの可能性が高く不具合とは関係がなさそう)


2.BufferedInputStreamをかましたほうが、パフォーマンスがよくなりそう。
(でも、不具合とは関係がない)


3.OutputStreamがclose()されないことが、あるかも。
(不具合とほんのちょっぴり関係がある可能性もあるかも)

} finally {
  if (in != null) {
    in.close();
  }
  if (out != null) {
    out.flush();
    out.close();
  }
}

 finally節です。
 ここは必ず通るはずですが、in.close()の行で例外が発生するとその後の行が実行されません。
 そもそも、InputStream や OutputStream を close するときの例外がどういう場合に発生するのかよくわからないのですが、発生する可能性がある限り、ちゃんとキャッチしないとメソッドの呼び出し元に制御が移ってしまいます。

 めんどくさくても、後に実行しなければいけない行が控えているときは、こうしたほうがよいと思います。

} finally {
  if (in != null) {
    try {
      in.close();
    }
    catch (IOException ex) {}
  }
  if (out != null) {
    out.close();
  }
}

 SocketOutputStream の flush() は何もしないので、書く必要はありませんし、害もないですが、一応例外が発生するメソッドですし、将来もし中身が実装されれば、実際に例外が発生してしまいます。
 念のために書いておきたい場合は、finally節ではなくwhile文のあとに書いたほうがよいと思います。

 しかし、もし、この問題が発生したとしても、

>まれに表示されずに×印が出てしまうことがあります。

 この現象のイメージとはなんとなく違うような気がしますねぇ。

 サーブレット固有の問題の場合は、お手上げですので、経験者の方の投稿を待ってください。

投稿日時 - 2005-05-18 08:23:23

お礼

回答、ありがとうございます。

>1.breakが変なところにある。

ご指摘の通り、投稿時の記述ミスです。
本来は以下のように記述していました。

  while ((b = in.read()) != -1) {
    for(int i=0 ; i< 10 ; i++ ){
      try {
        out.write(b);
        break ;
      }catch(IOException e){
        if( i == 9 ){
          throw e;
        }
      }
    }
  }

特定の画像ファイルで、out.write(b)でIOExceptionが発生する事があるようでしたので、失敗した場合は適当な回数だけ再処理を行うようにしています。
ご指摘の通り、質問した問題には関係ないと思います。

>2.BufferedInputStreamをかましたほうが、パフォーマンスがよくなりそう。

参考になります。実装を考えてみます。

>3.OutputStreamがclose()されないことが、あるかも。

確かに。out.close()が行われないのは拙いですね。修正します。
投稿後いろいろと見た結果、out.close()時にエラーが発生する場合があることがわかりました。

java.net.SocketException: Software caused connection abort: socket write error

と出ているようです。
想像ですが、この問題の場合、IMGタグが3つある為、サーブレットとの通信が3つ同時に行われる事になると思います。この辺、何か関係してくるのでしょうか?


更なるご指摘、お待ちしています。

投稿日時 - 2005-05-18 11:02:05

あなたにオススメの質問