モバイルサイトなどのファイルアップロード機能で、通常のファイルセレクタのフォームではなく、ファイルアップロード用のボタンを設置してファイル選んだ瞬時にアップロードを開始したい場合がある。
こんなイメージ。(DevHubというチャットツールのモバイルサイト実装したアップロードボタン。右端の黒いボタン)
メリットとしては、ファイル選択直後にアップロードが開始するのでアップロードまでの手順を削減できる。
html
html は input の type="file" タグを非表示で設置し、その代わりボタンを表示する。(以下の例は TwitterBootstrap を使っている前提)
<input type="file" id="upload_chat" name="file" style="display:none"></input>
<button id="upload_chat_button" class="btn btn-small btn-inverse"><i class="icon-upload icon-white"></i></button>
js
ボタンの click イベントでフォームのクリックイベントを発火することでファイル選択フォームが開かれる。iPhoneの場合はここでカメラ起動かアルバム内の画像を選択するUIが表示される。
$('#upload_chat_button').click(function(){
$('#upload_chat').click();
return false;
});
続いてフォーム側の 'change'イベントを実装し、ajax でファイルの情報を 'POST' する。
このイベントはユーザがアルバム内のファイルを選択したりカメラで写真を撮って「写真を使用」を選択した際に発火する。
$('#upload_chat').on('change', function(){
return function(event){
var file = $(this).prop('files')[0];
var formData = new FormData();
formData.append('file', file);
$.ajax('/upload' , {
type: 'POST’,
contentType: false,
processData: false,
data: formData,
error: function() {
//アップロードエラー時の処理
},
success: function(res) {
//アップロード成功時の処理
}
});
return false;
}
});
サーバサイド
サーバサイドではファイル情報のPOSTを元にファイルを保存などの処理を行う。
例として node.js の express サーバでファイルを保存するコードはこんな感じ。
var fs = require('fs');
exports.post = function(req, res) {
var tmp_path = req.files.file.path;
var file_name = "hoge.jpg";
var target_path = './static/uploads/' + file_name; // ファイルを保存する場所
fs.rename(tmp_path, target_path, function(err) {
if (err) {
throw err;
}
fs.unlink(tmp_path, function() {
if (err) {
throw err;
}
// ファイル保存成功時の処理
res.send({message: "アップロード成功!"});
});
});
};
これでモバイルでもアップロードボタンから簡単にファイルをアップロードできるようになる。
[2016/09/06 追記]
express を 4系に上げたら上記コードでは動かなくなった。対応版は以下。
https://github.com/volpe28v/DevHub/blob/master/routes/upload.js