JavaのWebアプリケーション開発フレームワークによる、Webサイト開発の顛末記です。

EclipseのMavenを使った、Spring-MVC、Thymeleaf、MyBatis 等のプログラミングテクニックを、
備忘録的に記録しています。実際に動くソースコードを多用して説明していますので、
これからEclipseや、Spring-MVCを始めたいと思っている人にとって、少しでも参考になれば幸いです。
■応用の森 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世代の機能なので、動作可能なブラウザは限られています。
以下主なブラウザの種類とバージョンを列挙しておきます。
ブラウザ 対応バージョン
Internet Explorer(Edge) 10.0以降
Fire Fox 3.6以降
Chrome 6.0以降
Safari 5.1以降
Opera 11.1以降
要するに、各主要ブラウザの最新版を使っていれば(多分)動くと思って間違いなさそうです。

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がどんなものかデバッグしてみたので参考として列挙しておきます。
ファイルタイプは数え上げればきりはありませんが、だいたいこれぐらい列挙してあれば十分でしょう。
拡張子 type
txt text/plain
html text/html
xml text/xml
csv 空 (unknown?)
png image/png
jpeg/jpg image/jpeg
gif image/gif
ico image/x-icon
svg image/svg+xml
mp3 audio/mp3
mov video/quicktime
mp4 video/mp4
m4v video/mp4
webm video/webm
ogv video/ogg
zip application/x-zip-compressed
exe application/x-msdownload
doc application/msword
pdf application/pdf
xls application/vnd.ms-excel
xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
ods application/vnd.oasis.opendocument.spreadsheet
ただ、FileAPIのファイルタイプは正直あまり信用しすぎない方が無難です。
例えば、png画像ファイルの拡張子を無理やり txt に変更してドロップすると、ファイルタイプは text/plainと表示され
悲しい思いをすることがあります。
あくまで参考程度に考えておいた方がよさそうですね。