Ajaxでファイルダウンロードとアップロード

| コメント(0)

WalkDB2

以前も書いたが、これまで歩いた散歩のコースをDB化して管理・検索するアプリケーションWalkDBを自作している。単に趣味のデータをいじりまわすためだけでなく、そのときどきのおもしろそうな技術的な要素をとりこんで試すのも目的の一つだ。従来べたのServletで書いていたのを2004年10月にStrutsフレームワークに移植してからは大きなアーキテクチャーの変更はしていなかったが、それでもO/Rマッピングライブラリのibatisを採用したりだとか、無償で公開されている全国市区町村境データを使って市区町村による絞り込み検索をサポートしたりなど、それなりにブラッシュアップを重ねてはいた。

もともと画面遷移が必要ないアプリなのに、Strutsのしきたりに従って律儀に画面遷移を行ってきたが、この辺で、Strutsを捨て、最近流行のAjaxで、必要なデータを非同期に取得して画面の一部を書き換えるようなアーキテクチャーにすることにした。名付けて、WalkDB2.0。

ライブラリはDWRを使う。サーバ側でPOJOのオブジェクトとメソッドを定義しておけば、そのメソッドをAjaxで呼び出すためのクライアント側のコードを自動的に生成してくれる便利なやつだ。

さてここからがようやく本題だ。検討してみると、この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の処理を発行し、その中で先ほどアップロードされたファイルを処理する。

といった感じで、一応できることはできたが、やはり無理矢理感がただよう。もっといい方法をそのうち思いつくかも知れない。

コメントする