-
result type に、StreamResultを使います。
- ファイルをダウンロードさせたい。
- DB(とか)からファイルパスを引っ張ってきて、
- 日本語名の付いたファイル、
- 拡張子はjpgだったりdocだったり。
2.0.12で可能な形のサンプルはwebに落ちてました。そいつを2.1.6で動かしてみたら
[inputName]ってキーで、inputStreamを寄越せや!
とStruts2様が仰りやがりますので、Struts2のソースを読んで、書き換えたらうまくいきました。
情報共有の意味で上げておきます。もっといい書き方があるよ、って人は指摘ください。
要件これ。
アノテーションはこのように書きます。
Struts2.1.6
@Result(name = "download", type = "stream" , params = { "inputName", "inputStream", "contentType", "application/octet-stream; charset=UTF-8", "contentLength", "${ contentLength }", "contentDisposition", "attachment; filename = ${fileName}" })ちなみにStruts2.0.12
@Result(name = "download", type = StreamResult.class, value = "inputStream" , params = { "contentType", "application/octet-stream; charset=UTF-8", "contentLength","${ contentLength }", "contentDisposition","attachment; filename= ${fileName}" })paramsの中はMap状になってて、パラメータが足りないとき、Struts2に怒られます。Struts2.1.6時点では4つ。
- inputName
- contentType
- contentLength
- contentDisposition
package 適切な import 適当に @Results({ @Result(name = "download", type = "stream" , params = { "inputName", "inputStream", "contentType", "application/octet-stream; charset=UTF-8", "contentLength", "${ contentLength }", "contentDisposition", "attachment; filename = ${fileName}" }) //TODO 他の戻りも定義するかい? }) public class downloadAction { public String fileName; public long contentLength; public InputStream inputStream; public String execute() throws Exception{ //TODO ダウンロードじゃない場合もあるなら、分岐を仕込んで、successとかerrorとかを返すべし。 return this.download(); } private String download() throws Exception{ //TODO 実際は、DBからファイルパスを取ってきて・・・ private String img = "C:\\TEMP\\ほげ.png"; File downFile = new File(img); try { this.inputStream = new BufferedInputStream(new FileInputStream(img)); this.fileName = URLEncoder.encode(downFile.getName(), "UTF-8"); this.contentLength = downFile.length(); } catch (FileNotFoundException e) { e.printStackTrace(); } return "download"; } }ダウンロードダイアログが出て、直で開くと、日本語ファイルは、タイトルが文字化けるです。残念。
かなり当ったけど、無理っぽい?。
(X URLエンコードをWindows-31JとかSJISとか、application/octet-stream; charset=をWindows-31JとかSJISとか)
そこは割りきりかなと、現時点では思います。保存しなさいってことで話を持って行くのがベターかなあと。
contentDispositionの値を、attachment → inlineと書き換えることで、.xlsとか.docを、ブラウザ内で開くこともできるかも。
ちなみにTIFFを開かせようとして、
@Result(name = "download", type = "download" , params = { "inputName", "inputStream", "contentType", "image/tiff; charset=UTF-8", "contentLength", "${ contentLength }", "contentDisposition", "inline; filename = ${fileName}" })とやったけど、対応するアプリケーションが、クライアントにあるや無しや?になるんで、サーバーサイドでの対応は無理?。
≪関連記事≫
アノテーションでの定義はかなり苦しい(無理?) →できました!。
@いう間にWebアプリを作れる「Struts 2」入門 ←このサンプルでハマった人(俺)に捧ぐ。