ダウンロードしたいわけじゃない場合
今、ファイルを管理するページを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兄さんも試されているように、日本語ファイルをマルチブラウザでダウンロードさせるのは少々厄介である。
今のところ、利用者はFirefoxとIEだけなので、きったないソースだが、以下のように対応した。
@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; }
うん。これは汚い。スマートさがないな。