HTML5 の Drag and Drop API を使うことで、ブラウザにドロップされたファイルの情報を扱うことが出来ます。そして File API を組み合わせることで、ファイルの中身まで扱うことが出来るようになります。
そして FormData オブジェクトと XHR を組み合わせることでアップロード処理までを実装することが出来ます。完成図はこんな感じです。
今回は JavaScript の処理が中心です。jQuery を使っているので追加してくださいね。
$(function () { var uploadFiles = function (files) { // FormData オブジェクトを用意 var fd = new FormData(); // ファイル情報を追加する for (var i = 0; i < files.length; i++) { fd.append("files", files[i]); } // XHR で送信 $.ajax({ url: "@Url.Action("upload", "file")", type: "POST", data: fd, processData: false, contentType: false }); }; // ファイル選択フォームからの入力 $("#form").bind("change", function () { // 選択されたファイル情報を取得 var files = this.files; // アップロード処理 uploadFiles(files); }); // ドラッグドロップからの入力 $("#target").bind("drop", function (e) { // ドラッグされたファイル情報を取得 var files = e.originalEvent.dataTransfer.files; // アップロード処理 uploadFiles(files); }) .bind("dragenter", function () { // false を返してデフォルトの処理を実行しないようにする return false; }) .bind("dragover", function () { // false を返してデフォルトの処理を実行しないようにする return false; }); });
Firefox 4 などでは FormData オブジェクトが用意されているので、非常に面倒な multipart/form-data の処理を行う必要がありません。IE10 PP2 でも対応したと開発者ガイドに書いてあったのですが、現時点のバージョンでは非対応のようなので使えませんでした。今後に期待します。
それでは HTML 側を見てみましょう。こっちは大したことないです。
<h2>Form Version</h2> <input id="form" type="file" multiple="multiple" /> <br /> <h2>Drag and Drop Version</h2> <div id="target" draggable="true"> <br /> <br /> <span>Drop File(s)</span> <br /> <br /> <br /> </div>
違いは type="file" の input タグに multiple="multiple" を追加しているだけです。IE10 PP2 から使えるようになった、複数のファイルを選択可能にするための属性です。
そしてドラッグドロップのターゲットになっている div タグには draggable="true" を追加しています。この設定をしないとドロップターゲットになりません。
最後にコントローラとアクションですが、引数に追加するだけです。もはや説明もいらないでしょう。
public class FileController : Controller { public ActionResult Upload() { return View(); } [HttpPost] public ActionResult Upload(HttpPostedFileBase[] files) { // 何かやる!! return View(); } }
今回はサンプルなので Upload アクションで JSON とか返してないんですけど、本来なら何らかの処理結果を返して JavaScript 側で何とかしてくださいね。
それにしても HTML5 はいろいろ出来て楽しいですね。そういえば File API と書いておきながら File Reader とか使ってなかったですね、まあいいや。