ドラッグ&ドロップでファイルをアップロードする(IE対応版)
※jQuery前提です
時代に逆行してる感じがすごいですが。
以前作ったのはこちら。
ドラッグ&ドロップでファイルをアップロードする(最低限版) - アナログCPU:5108843109
ドラッグ&ドロップでファイルをアップロードする(ちょっとリッチ版) - アナログCPU:5108843109
またアップロードフォームを作る機会があったのですが、
今回はIEに対応していないとダメとのことで、↑では動かないようだったので作り直しました…。
い、今更!? IE対応すんの!?!?とは思いましたが仕方ない…。
以前作ったやつは
「フォームオブジェクトにアップロードするデータをぶちこみ、それをinput(file)要素に入れ直す。あとは普通にsubmitするだけ」
という主旨の作りだったのですが、
IEはinput要素に入れる部分がブラウザ仕様で弾かれる様子。
今回は、フォームオブジェクトをそのままJSからPOSTする方向です。
submitでないので完了時に結果表示などを伴うページ遷移をどうしても入れたい場合は厄介。
では手短に。
ドラッグ&ドロップするエリアを↓とします。(HTML)
<div class="droparea"></div>
そしてJSがこちら。
let fd = new FormData(); // ドラッグでエリアの中に入ったときの処理 $('body').on('dragover', '.droparea', function(e){ /* 見た目を変えるなどの処理 */ }); // ドラッグでエリアの外に出たときの処理 $('body').on('dragleave', '.droparea', function(e){ /* 見た目を変えるなどの処理 */ }); // エリア外でドラッグしたりドロップしたりしたときの処理(無視する) $('body').on('dragover', function(e){ e.preventDefault(); }); $('body').on('drop', function(e){ e.preventDefault(); }); // エリア内でドロップしたときの処理(フォームオブジェクトに突っ込む) $('body').on('drop', '.droparea', function(e){ e.preventDefault(); let files = e.originalEvent.dataTransfer.files; for ( let i = 0, len = files.length; i < len; i++ ) { fd.append('userfile[]', files[i]); } // 送信 ※ドラッグ&ドロップ直後にアップロードしない場合は適宜外に出して調整 send(); }); // 送信処理 function send(){ let xhr = new XMLHttpRequest(); xhr.open('POST', encodeURI('/upload.php')); // ★POST先:適宜変更する xhr.onreadystatechange = function(){ if ( xhr.readyState == 4 ) { if ( xhr.status == 200 ) { // 成功時の処理 console.log(xhr.responseText); //例えばこれだとPOST先の返却値をコンソールに表示 } else { // 失敗時の処理 } } }; xhr.send(fd); }
アップロード先(↑の例だとupload.php)は今回とあんまり関係ないので最低限の動作確認分だけ。
<?php var_dump($_FILES);
ちなみにファイル以外のものをPOSTしたいときもファイルと同じように追加できます。
「fd.append('キー名', 値);」「fd.set('キー名', 値);」のいずれかで追加が可能で、文字通りappendは「追加」、setは「もし同じものがあれば上書き」です。
…が、IEはsetが使えず、今回の趣旨で言うと、appendだけでなんとかする必要があります。ええ……
FormData.append() - Web API | MDN
FormData.set() - Web APIs | MDN
PHP側では通常通り$_POSTで受け取れます。