今日は画像ファイルのアップロードを実装する方法のご紹介です。
ファイルアップロード時の画面遷移はしないケースで考えます。1ページ完結型です。
Ajaxは使わず、シンプルに通常のフォーム送信で実装します。
やり方
ファイル送信自体にはフォーム要素を使います。
<form id="FileUpload" name="upload" method="post" action="/api/upload" target="upload-image" enctype="multipart/form-data">
<input type="file" name="image" />
<input type="submit" name="submit" value="送信" />
</form>
<iframe id="FileUploadIframe" name="upload-image" style="display: none;"></iframe>
ここで重要なのは、非表示のiframeを配置することと、
フォーム要素のtarget属性値にiframeのname属性を指定して、iframeにフォームでのやりとりを任せてしまうことです。
これで普通にフォーム送信をして、サーバからはレスポンスとしてHTMLを返してもらいます。
JSONを返してもらいたい場合はiframeからJSONを受け取れるようにscriptタグの中でメソッドを定義してその中に格納してしまいましょう。
<!-- サーバが返すHTML -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
// iframeの中で呼ばれるのでwindow.parentで親フレームからアクセスできるようにする
window.parent &&
window.parent.Global &&
window.parent.Global.sendJSON &&
window.parent.Global.sendJSON({
"meta": {
"code": 200,
"status":"success"
},
"content": {
"id": "*********"
}
});
</script>
</body>
</html>
イメージとしてはJSONPに近いですね。
返り値の処理はあらかじめwindow.Global.sendJSON
というメソッドをグローバルに用意しておきます。
window.Global.sendJSON = function(data) {
var response = data.content;
if (data.meta.status === 'success') {
// 通信成功時の処理
} else {
// 通信失敗時の処理
}
};
サーバからレスポンスがない場合を想定してタイムアウトを設定しておくとより親切です。
アップロードに時間がかかることも考慮すると、ファイルサイズの上限を決めてしまうのもアリだと思います。
ファイルプレビューを表示したい
FileAPIを使うと簡単に実装できます。(注:IE10以上対応)
HTML
<form id="FileUpload" name="upload" method="post" action="/api/upload" target="upload-image" enctype="multipart/form-data">
<input type="file" name="image" />
<input type="submit" name="submit" value="送信" />
</form>
<iframe id="FileUploadIframe" name="upload-image" style="display: none;"></iframe>
<!-- プレビュー挿入用の要素を用意する -->
<div id="FileUploadPreview"></div>
Javascript
var form = document.forms.upload,
input = form.input,
submit = form.submit,
preview = doc.getElementById('FileUploadPreview');
function preview(file) {
if (file.type.match(/image/)) {
var fr = new FileReader();
fr.onload = function(e) {
var img = new Image();
img.src = e.target.result;
preview.innerHTML = '';
preview.appendChild(img);
};
fr.readAsDataURL(file);
}
}
if (!window.File) {
return;
} else {
submit.addEventListener('click', function(e) {
var file = input.files[0];
preview(file);
}, false);
}
IE9以下もサポートする場合は、フォーム送信時にサーバからプレビュー用画像を返してもらい表示しましょう。