アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

('ω') < イザユケエンジニャー

ドラッグ&ドロップでファイルをアップロードする(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で受け取れます。