ダウンロードしたいわけじゃない場合

今、ファイルを管理するページをSAStrutsで作っている。
アップロードもできて、アップロードされたファイルをダウンロードできる1枚もののページである。ひととおり完成しているのだが、たとえば画像なんかであれば、ダウンロードしてから表示するのではなく、ブラウザ上で表示したいと思うわけである。

ブラウザで表示するには

ダウンロードについては、ResponseUtil.download() で出来るが、表示に関しては適当なメソッドがない。やりたいことは、

  • ファイルの拡張子からMIMEタイプを取得し、Content-Typeに指定する。
  • あとはレスポンスに流し込むだけ

である。先述のResponseUtil.download() は内部でContent-Typeを設定しているため、使えないのだ。なので、download()のソースを見ながら、Action内ですることにした。

  @Execute(validator = false, urlPattern = "view/{id}", input = "index.jsp")
  public String view() {
    File f = findFile();
    try {
      FileTypeMap defaultFileTypeMap = MimetypesFileTypeMap
          .getDefaultFileTypeMap();
      String contentType = defaultFileTypeMap.getContentType(f.getAbsolutePath().toLowerCase());
      response.setContentType(contentType);
      response.setContentLength((int) f.length());

      OutputStream out = response.getOutputStream();
      try {
        InputStreamUtil.copy(FileInputStreamUtil.create(f), out);
        OutputStreamUtil.flush(out);
      } finally {
        OutputStreamUtil.close(out);
      }

    } catch (IORuntimeException e) {
      // do nothing
    } catch (IOException e) {
      throw new IORuntimeException(e);
    }
    return null;
  }

日本語ファイルの問題

http://nyaos.org/d/index.cgi?p=%282009.02.02%29#p1 でzetamatta兄さんも試されているように、日本語ファイルをマルチブラウザでダウンロードさせるのは少々厄介である。

今のところ、利用者はFirefoxIEだけなので、きったないソースだが、以下のように対応した。

  @Execute(validator = false, urlPattern = "download/{id}", input = "index.jsp")
  public String download() {
      File f = findFile();
      try {
          String userAgent = request.getHeader("user-agent");
          String encode = "UTF-8";
          if (userAgent.indexOf("MSIE") != -1) {
              encode = "MS932";
          }
          String filename = new String(f.getName().getBytes(encode),
                  "ISO-8859-1");

          ResponseUtil.download(filename, new BufferedInputStream(
                  new FileInputStream(f)), (int) f.length());
      } catch (IORuntimeException e) {
      } catch (IOException e) {
          throw new IORuntimeException(e);
      }
      return null;
  }

うん。これは汚い。スマートさがないな。