新年早々はまったことが、Ajaxでファイルのダウンロードすることだった。
発端はjQuery File Treeを利用したことだ。
すごく便利なのだが、リンクをクリックしたときに専用のfunctionがコールされるだけなのだ。
その引数にファイルパスが一応渡ってはくるのだが、
単にlocation.hrefの指定をするだけでは、ブラウザで開かれてしまうし、拡張子によっては開けないのもある。
今回は単純にブラウザに処理させてファイル保存ダイアログを表示させたかった。
他にも試行錯誤したが、javascriptベースでは良い方法が見つからなかった。
そこでDWRを使っていたこともあり、サーブレットでダウンロードしようと試みた。
そこでまた問題発生。
Ajax経由の呼び出しだけではファイルのダウンロードが困難なことが分かった。
困り果てていると、以下のサイトを見つけた。
http://chez-sugi.net/journal/20070306.html
------------ 抜粋 --------------------
検討してみると、このAjax経由の呼び出しだけでは実現できない機能があることがわかった。
ファイルのダウンロードとアップロードだ。
ダウンロードはレスポンスをAjax的にjavascriptの関数が受け取るのではなく、
古典的にブラウザに処理させてファイル保存ダイアログを表示してもらわなくてはいけない。
アップロードはどうしても<input type="file" ... >を含むformをsubmitする必要があり、
サーバ側でもDWRと別の枠組みでそれを処理しなくてはいけない。
しかも、ふつうにsubmitしてしまうと画面遷移が発生してしまう。
基本的に非同期で処理を行い画面遷移が発生しないようにするという当初の目標をキープしつつ、
できるだけDWRの枠組みの中で処理を実装する方法を考えてみた。
ダウンロードに関しては、DWRでファイル作成までを行い、
その完了後呼ばれるクライアント側のコールバックの中から、location.href = ...で
ファイルダウンロード専用サーブレットのURLに遷移するようにした
(レスポンスのヘッダでContent-dispositionをattachmentにしているので、
実際は遷移は発生せずファイル保存ダイアログが開く)。
アップロードに関しては、あらかじめiframeを用意しておいて、
formのtargetをそちらにすれば画面遷移しないようにすることができる。
サーバ側ではファイルアップロード専用のサーブレットがformからの入力を受けとめ、
アップロードされたファイルを保存する。クライアント側ではiframeのonloadイベントハンドラ中で
(IEではonreadystatechangeイベントハンドラの中でreadystateがcompleteになったときに)
DWRの処理を発行し、その中で先ほどアップロードされたファイルを処理する。
---------------------------------------
なるほど、ファイルの作成部とダウンロード部を分けるのか。
この方針で作成してみるとうまく行った。
感謝です。