Fine Uploader は便利
Fine Uploader は他ライブラリへの依存がなく、高機能で主要ブラウザはもちろん、IE8+にも対応していて助かる。
助かるんだけど、機能がありすぎて少しとっつきにくいのが難でいつも忘れる。
ここでは、高機能っぷり発揮のデモほどのものは不要で、必要最低限でいいって時のサンプルをメモ。
「CORE」のみを利用
Fine Uploader には 基本機能(CORE) と UI機能 というのがある。
UI機能は独自のテンプレートエンジンとか使って簡単にUI周りが作れるようなやつなんだけど、今回は割愛し、使うのはCOREの機能のみ。
(UI機能にはすべてのCORE機能が含まれる)
COREのみを利用する場合、インスタンスは以下のように作成する。
var uploader = new qq.FineUploaderBasic({
// ...コンフィグ...
});
qq
というのは Fine Uploader の本体オブジェクトで、qq
という名前で決まってる(何の略かは知らんけど)。
jQueryでいう $
みたいなやつ。
ちなみにUI機能を使う時は FineUploaderBasic
部分が FineUploader
(Basicがない) になる。
実現したい要件
今回は以下のような超シンプルなもの。
-
input type="file"
ではなくボタンのクリックで画像ファイルを選択 - 選択するとサムネイルをプレビュー
- 送信ボタンでアップロード開始
- アップロードできる拡張子を限定したい
- 送信完了したらなにかしたい
コード
HTMLとCSS
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>サンプル</title>
<style>
/* プレビュー画像のCSS */
#preview {
display: block;
max-width:100px;
max-height:100px;
border:1px dashed #ddd;
}
</style>
</head>
<body>
<button id="button">ファイル選択</button>
<button id="upload">アップロード</button>
<!-- プレビュー用画像 -->
<img id="preview">
</body>
</html>
JavaScript
すべての CORE 用オプションは公式ドキュメントで。
オプションに加え、用意されている drawThumbnailメソッド と uploadStoredFilesメソッド も使用している。
// UI用の FineUploader でなく FineUploaderBasic を使用
var uploader = new qq.FineUploaderBasic({
// 「送信」ボタンでアップロードするため false に
autoUpload: false,
// ファイル選択ボタン
button: document.getElementById('button'),
// 検証
validation: {
// アップロードできる拡張子を限定
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png']
},
// POST先
request: {
endpoint: location.href
},
// コールバックたち
callbacks: {
// エラーがあった時
onError: function(id, filename, message, xhr) {
alert(message);
},
// ファイルが選択された時
onSubmit: function(id, filename) {
// qq.FineUploaderBasic インスタンス
var self = this;
// drawThumbnail メソッドでプレビュー用画像に描画
// (src 属性に data スキーマがセットされる)
this.drawThumbnail(id, document.getElementById('preview'));
// アップロードボタンにクリックイベントを付加
document.getElementById('upload').addEventListener('click', function(e) {
e.preventDefault();
// クリックされたらアップロード開始
self.uploadStoredFiles();
}, false);
},
// アップロードが完了した時
onComplete: function(id, filename, response, xhr) {
alert('「' + filename + '」のアップロード完了!');
}
}
});
全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>サンプル</title>
<style>
#preview {
display: block;
max-width:100px;
max-height:100px;
border:1px dashed #ddd;
}
</style>
</head>
<body>
<button id="button">ファイル選択</button>
<button id="upload">アップロード</button>
<img id="preview">
<script src="https://cdnjs.cloudflare.com/ajax/libs/file-uploader/5.10.0/fine-uploader.min.js"></script>
<script>
var uploader = new qq.FineUploaderBasic({
autoUpload: false,
button: document.getElementById('button'),
validation: {
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png']
},
request: {
endpoint: location.href
},
callbacks: {
onError: function(id, filename, message, xhr) {
alert(message);
},
onSubmit: function(id, filename) {
var self = this;
this.drawThumbnail(id, document.getElementById('preview'));
document.getElementById('upload').addEventListener('click', function(e) {
e.preventDefault();
self.uploadStoredFiles();
}, false);
},
onComplete: function(id, filename, response, xhr) {
alert('「' + filename + '」のアップロード完了!');
}
}
});
</script>
</body>
</html>
これで要件を満たした。
とりあえず上記コードをCodePenで動作確認できるようにした。
(送信すると500エラーが出るけど大丈夫)
サーバー側
サーバーへは XMLHttpRequest(Ajax) で送信されるけど、普通に multipart/form-data
でアップロードされたようなデータが来る。
返却は JSON 形式にし、成功なら {"success": true}
、エラーなら {"success": false}
または {"error": "メッセージ"}
を返す。
(返す JSON には success
error
以外のデータも含んでOK)
ちなみに Fine uploader の強力な機能に chunking がある。
これはアップロードファイルを分割して送信する機能で、例えばモバイル等でアップロード中に接続が切れても途中から再開(resume)できる。
また、エラー時にリトライできたりもするので便利。
chunking を使う場合の流れは
- JavaScriptで chunkingオプション を設定
- ファイル送信(自動で分割。非同期で順不同)
- サーバーで分割ファイルをひとつずつ一時保存(番号情報が来るので、その番号をファイル名にするといい)
- 完了したら一時ファイルを順番に結合(完了用のURLを別にしたり可)
みたいになる。
(chunking 時の分割ファイルの mime type は application/octet-stream
になるので注意)