■応用の森 File APIを使用した、Ajaxファイルアップロードサンプル |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
今回は、<input type="file">要素を使用しないファイルのアップロード処理のサンプルプログラムの紹介です。 何をいまさら、、、とか思う人もたくさんいるとは思いますが、まぁおつきあいください。 ちまたでは、dropzone.js とかいう ファイルアップロードツールがスタンダードっぽいみたいですが、勉強ということもあり、 これらの便利ツールは使わないで実装してみることにしました。 HTML5からJavaScriptの機能として、FileAPI と FormData という新しい機能が加わりました。 FileAPIは、ざっくりいうとローカルのPCのファイルをJavaScriptで扱えるようにした仕様です。 ローカルなファイルをjavaScriptで読み書きできるようにした機能ですが 今回は、ドラッグ&ドロップの機能を利用して、アップロードファイルの選択を行います。 FormDataは、HTMLの <form>タグをオブジェクト化したようなものと言えばわかりやすいでしょうか? <form>タグ内の要素をまとめて、FormDataクラスにセットすることもできますし、 <form>タグが無いようなHTMLでも、FormDataクラスを使用することで疑似的な formをsubmitすることが可能です。 これまでは、ブラウザ上でファイルのアップロードを行う場合はどうしても <form>タグの<input type="file">要素を使用して処理していましたが 今回は、これまで標準だった慣例の手法を使用しないで、 FileAPIでドラッグ&ドロップしたファイル情報を、FormDataクラスにセットして、 Ajaxでサーバーにアップロードするというサンプルをご紹介します。 <input type="file">を使用する必要がないので、表現の自由度がはるかに高まりましたv(^^)v 上が、実際の動作サンプルです。 メッセージに従って、操作してみてください。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
それでは、簡単にプログラムの解説です。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1)コントローラ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
今回はView側のJQuery(JavaScript)が重要になるのですが それは後で説明することにして、まず簡単なコントローラから。 src/main/java/jp/dip/arimodoki/cntl/FileUploadAjax.java このコントローラは、ファイルアップロード完了時、Ajax呼び出し側に、 viewではなくて文字列を返したいので、@RestControllerアノテーションを使用します。 最初のメソッド fileuploadajax() メソッドは、単純に初期画面を表示するためだけのハンドラメソッドです。 ModelAndViewクラスを返却していますが、 このあたりの解説は、「応用の森 Spring-MVC編 No001:Spring-MVCにおけるコントローラの戻り値」 で、簡単ですが説明しているのでここを参考にしてください。 2番目のメソッド uploadajax() が、Ajaxで呼び出される、ファイルアップロードハンドラメソッドです。 @RequestParam("uploadfile") MultipartFile uploadfile パラメータで viewからのファイル情報を受け取りますが、ここはサンプルなので 受け取ったファイルは何もせずに放置(垂れ流し)ています。 ハンドラのパラメータ等は特殊なことはなくて、通常のサーバー側ファイルアップロード処理と何らかわりません。 ファイルを受け取った結果の文字列を、view側Ajaxの戻り値として返却します。 (具体的には、Ajaxに返却するステータスコードをJSON文字列として返しています) 参考までに、サーバー側での最大ファイルザイズチェックとか、例外処理とかの例は、 「応用の森 Spring-MVC編 No002:ファイルのアップロード」で紹介していますので こちらも参考にしてみてください。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2)View(HTML) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
今回の一番重要な部分です。 JQuery(JavaScript)で、FileAPIを使ってファイルをアップロードする処理を解説します。 と、その前に FileAPIやFormDataは、HTML5世代の機能なので、動作可能なブラウザは限られています。 以下主なブラウザの種類とバージョンを列挙しておきます。
WebContent/fileuploadajax.html ソースの重要と思われるところを赤字で表示してみました。 まず、下の方のHTML部本体ですが、 これまでのファイルアップロードの慣例であった、<input type="file">タグが存在しません。 それどころか、<form>タグすらどこにもありませんね!。 その代わりに、ファイルをドラッグする<div>タグ領域がぽつんと一つだけ配置してあります。 この<div>タグに、「droppable」というIDを付与しておきます。 jQuery部は、このID「droppable」に対して操作を行います。 jQuery部では、FileAPIの手順がごちゃごちゃ書いてありますが、 ネットを検索すると、どれも似たり寄ったりの説明が見られるので ここでは詳しくは説明しません。各自ネットを探してみてくださいな。 ※1)ファイルドロップ時のイベントハンドラ ファイルをドラッグして、「droppable」エリアにドロップした時に発生するイベントハンドラです。 ネット上のサンプルでは、ここでFileReaderを使って、ドロップされたファイルを読み込んだりしている サンプルが多いのですが、今回はファイルの中身を見たいわけではなくて アップロードしたいだけなので、FileReaderの部分は使いません。 ※2)ファイル情報の保持 イベントハンドラのイベント(event)にドロップしたファイル情報が渡ってくるので、 後で「アップロード」ボタンをクリックした時に必要になるため 一旦、グローバル変数に保持しておきます。 ※3)FormDataオブジェクトへのファイル情報の追加 空のFormDataオブジェクトをnewします。 ※2)で覚えておいたファイル情報を、”uploadfile” という名前で、FormDataオブジェクトに追加します。 (今回はこれだけですが、ほかに必要なパラメータがある場合は、いくつでも追加することが可能) ※4)AjaxによるFormDataオブジェクトの送信 ※3)で作成したFormDataオブジェクトを、Ajaxのパラメータにセットして実行します。 サーバー側(Spring-MVC側)は、通常のファイルアップロード処理と同じ要領で アップロードされたファイルを取得します。 ※5)処理結果の描画処理 サーバー側が正常終了すると、Ajaxは、done()のコールバック関数で、 処理結果ステータスコードを受け取ります。 正常終了(0)の場合、ドロップ領域を送信完了の画像で上書きします。 具体的には、「Mission Complete」のロゴ画像が表示されます。 今回のサンプルは、ドロップできるファイルは一個だけですが、工夫すれば複数個ドロップすることもできます。 ドロップした時に、file.type を見ればコンテンツタイプも(一応)わかるので、 ファイルタイプを判定してエラーメッセージを表示することもできます。 一応ドロップしたファイルの種別で、file.typeがどんなものかデバッグしてみたので参考として列挙しておきます。 ファイルタイプは数え上げればきりはありませんが、だいたいこれぐらい列挙してあれば十分でしょう。
例えば、png画像ファイルの拡張子を無理やり txt に変更してドロップすると、ファイルタイプは text/plainと表示され 悲しい思いをすることがあります。 あくまで参考程度に考えておいた方がよさそうですね。 |
jQuery/JavaScriptの小技集 ![]() |
File APIを使用した、Ajaxファイルアップロードサンプル |