フォームにファイルアップロード機能を付け、更にそれをDrag&Dropで。しかもドロップした瞬間にアップロード始めたい(ajax)と思い他のサイトを参考にしながら作ってみました。具体的なサンプルを書いたので、コピペで動くと思います。
jQuery使っているので、使わない人はそこを置き換えればOKだと思います。
1.フォームでなくて良い
フォーム内でなくても良いです。大まかな流れは下記
- ドロップエリア(div class=”droparea”)を用意
- ファイルをドラッグ&ドロップ
- divのドロップイベントでファイルを取得
- フォームデータを作成 let fd = new FormData();
- fd.append(file)、その他パラメータを同じようにセット
- ajaxでデータ送る
2. HTML、cssはシンプルでOK
divの入れ物とその中にinputを入れておきましょう。
HTMLは下記にしました。ddareaなdivを大枠とし、input、div.dropareaを置いています。
<div class="ddarea" data-id="<?php echo $target_id;?>">; <input type="file" name="file" class="inputfile"> <div class="droparea"> <p>;ここにファイルをドラッグ&ドロップするか、クリックしてファイルを選択</p> </div> </div>
対応するCSS。これで、600×200のdropareaが出来ました。inputは非表示にしておきます。
<style type="text/css"> div.droparea { width: 600px; height: 200px; border: 2px solid #gray; border-radius: 6px; text-align: center; overflow: auto; } div.droparea:hover { cursor: pointer; } div.droparea p { text-align: center; } input.inputfile { display: none; } </style>
3. javascript (ajax upload以外)
必要なのは、ドラッグ&ドロップしてきた時のイベント制御です。
注意点としては、ドロップエリア以外に間違ってファイルをドロップすると、そのファイルをブラウザが表示しようとするので、それをキャンセルすることが必要です。
jQuery使っているのでそれで書いてしまいますが、使わない場合も基本は同じです。
3.1 ドロップエリア以外のドロップ禁止
単純にHTMLに対してのドラッグオーバー、ドロップイベント処理を書けばOK。
$(function(){ //HTML自体にドラッグ&ドロップしても何もしないようにする $('html').on('dragover', function(e){ e.preventDefault(); e.stopPropagation(); }); $('html).on('drop', function(e){ e.preventDefault(); e.stopPropagation(); }); });
3.2 ドロップエリアに対してのドラッグ&ドロップ
div.dropareaに対して、ドラッグオーバー、ドロップ処理を書きます。ドラッグオーバー時は文字を変えてみましょう。ドロップ時にajax_upload()関数を呼んでいます。
$(function(){ //ファイルをエリア内にドラッグしてきた $('div.droparea').on('dragover',function(e){ e.preventDefault(); e.stopPropagation(); let p = ($this).find('p'); $(p).text("ここにドロップ"); }); //エリアから離れた(初期状態に戻す) $('div.droparea').on('dragleabe',function(e){ e.preventDefault(); e.stopPropagation(); let p = ($this).find('p'); $(p).text("ここにファイルをドラッグ&ドロップするか、クリックしてファイルを選択"); }); //ドロップ $('div.droparea').on('drop',function(e){ e.preventDefault(); e.stopPropagation(); let p = ($this).find('p'); $(p).text("アップロード中"); //fileを取得 let file = e.originalEvent.dataTransfer.files[0]; //ajaxファイルアップロード関数を呼ぶ(4で説明) ajax_upload(file); }); });
4. javascript (ajax ファイルアップロード部分)
ドロップされたので、ファイルをアップロードします。先ほどのdropイベント内でajax_upload(file)を呼んでいるので、その実装をします。
function ajax_upload(file) { let fd = new FormData(); fd.append("file", file); let options = { type:'POST', url: 'https://fileupload.abc/upload', data: fd, cache: false, contentType: false, processData: false, dataType: 'json' }; $.ajax( options ).done(function(d){ //json返ってきたので処理 }).fail(function(d){ }).always(function(){ //完了 }); }
フォームデータにappendしていけばパラメータ増やせるので、アップロードするファイルとデータを紐づけるなら、fd.append(‘target_id’, 15); とかやり、サーバ側でデータベースにid=15にこのファイルがアップロードされた的なtableを用意してinsertすればOKですね。
5. inputは、ドロップエリアのクリックイベントでinputを呼ぶ
inputはcssでdisplay:noneなため非表示です。クリックしようにも出来ないので、ドロップエリアのクリックイベントで、inputクリックを呼びます。
$(function(){ //ドロップエリアがクリックされたので、inputをクリックしたことにする //ファイル選択ダイアログが出る $('div.droparea').on('click', function(e){ e.preventDefault(); e.stopPropagation(); let elminput = $(this).parent().find('input'); $(elminput).click(); }); //input type="file"でファイル選択された $('input[name="file"]').on('change', function(e){ //ファイルを取得 let file = $(this)[0].files[0]; //ajaxファイルアップロード関数を呼ぶ(4で説明) ajax_upload(file); }); });
6. サーバ側(php)
普段使っているフレームワークや、ファイルアップロード php とかで検索すればサンプル出てくると思います。
7の参考リンクのコードそのまま
<?php //アップロードされたファイル名を取得 $filename = $_FILES['file']['name']; //ファイルサイズ取得 $filesize = $_FILES['file']['size']; //アップロード場所 $location = "upload/".$filename; //jsonで返す配列 $return_arr = array(); //uploadディレクトリにファイルをアップロード if(move_uploaded_file($_FILES['file']['tmp_name'],$location)){ //ここの処理不思議。(元サイトのまま) $src = "default.png"; if(is_array(getimagesize($location))){ $src = $location; } $return_arr = array("name" => $filename,"size" => $filesize, "src"=> $src); } //最後はjsonで返す(ajaxでjson指定しているので) echo json_encode($return_arr);
7.参考リンク

コメント
これ今日一日ずっと探して、非常に助かりました。
細かい点ですが、
$(this)が($this)になってる箇所があります。そこを直したら完全に動きました。
有用な記事をありがとうございました。
あ、確かに・・・($this)になっていますね・・・
見ていただきありがとうございます!