StreamResultを使った場合
WebWork2ではファイルの出力用にStreamResultというクラスが用意されています。
通常使うServletDispatcherResultではJSPやVelocityに結果出力を任せるところを、StreamResultは指定したInputStreamをクライアントに出力します。
FileDownloadActionの作成
getInputStream()で返したInputStreamの中身がServletOutputStreamに出力されます。
デフォルトではinputStreamですが、StreamResultが読み込むInputStreamの名前を変えることは出来ます。
public class FileDownloadAction extends ActionSupport { public String execute() throws Exception { return SUCCESS; } public InputStream getInputStream() { try { return new FileInputStream("c:/test"); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } }
xwork.xmlの設定
<action name="filedownload" class="ww2.examples.event.FileDownloadAction"> <result name="success" type="stream"> <param name="bufferSize">4096</param> <param name="contentType">application/octet-stream</param> <param name="contentDisposition">attachment; filename=test.file;</param> </result> </action>
- bufferSize: 出力時のバッファサイズ(初期値:1024)
- contentType: Content-Type(初期値:text/plain)
- contentDisposition: Content-Disposition(初期値:inline)
Action内で出力する場合
とりあえずAction内でHttpServletResponseを取得して直接出力すればやりたい放題なのでその方法も書いておきます。(非推奨)
FileDownloadBySelfActionを作成
ServletResponseAwareインターフェースを実装するとHttpServletResponseがセットされる(intercepterにservlet-configが含まれている必要あり)ので、取得したHttpServletResponseを使って直接ファイルを書き出します。
また、Resultの処理は行わないためexecute()の戻り値はActionインターフェースの定数NONEを返します。
public class FileDownloadBySelfAction extends ActionSupport implements ServletResponseAware { private HttpServletResponse res; public String execute() throws Exception { res.setContentType("application/octet-stream"); res.setHeader("Content-Disposition", "attachment; filename=text.file"); OutputStream out = null; InputStream in = null; try { out = res.getOutputStream(); in = new FileInputStream("c:/test"); CopyUtils.copy(in, out); out.flush(); } finally { IOUtils.closeQuietly(in); } return NONE; } public void setServletResponse(HttpServletResponse res) { this.res = res; } }
xwork.xmlの設定
Resultがないので超シンプルです。(実際のアプリではエラー時のResultは指定する必要がありますが)
<action name="filedownloadbyself" class="ww2.examples.event.FileDownloadBySelfAction" />
結果
当たり前ですが普通に使えます。もうServletAPI直接たたいてるんだから当たり前ですが。
独り言
やっぱりStreamResultを使う方がきれいな感じですねぇ。
とりあえず使えそうな独自のStreamResultもどきを作るか、もっと使いやすいように提案していくのがいいかも。