search
LoginSignup
35
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

【3分でできる】ライブラリなしでファイルをドラッグ&ドロップでアップロード

ライブラリなしでファイルをドラッグ&ドロップでアップロード

ライブラリなしでdropZoneを使ったファイルアップロードの記事が少なかったので書きました

注意

ライブラリなしと言ってますがajax通信にjQueryを使ってます
jQueryを使わない場合はこちらを参考にしつつ生jsで置き換えてください

ライブラリを使える人はこの記事の実装を参考にdropzone.jsというライブラリを使うといいかと思います

ドロップゾーンの実装

複数ファイルアップロードする場合はenctype=multipart/form-dataを入れてください

htmlの記述

    <div id="drop_zone">Drop a file here</div>
    <output id="list"></output>
    <form id="my_form" enctype=multipart/form-data>
        <input type="file" style="display:inline" name="upload_file">
        <br>
        <button type="button" onclick="file_upload()">アップロード</button>
    </form>

見た目

自分のサイトに合わせて調整してみてください

#drop_zone{
    width: 80%;
    height: 200px;
    border: 1px dotted black;
    border-radius: 1rem;
    margin: auto;
    margin-top: 2rem;
    font-size: 3rem;
}

dropzoneの処理

HTML5 rocksの記事を元に実装してます
詳しい解説は上の記事がわかりやすいです

//drop zoneの実装
function handleFileSelect(evt) {
  evt.stopPropagation();
  evt.preventDefault();

  files = evt.dataTransfer.files; // FileList object.

  // 以下に必要なFile Objectのプロパティを記述
  var output = [];
  for (var i = 0, f; f = files[i]; i++) {
    output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
                f.size, ' bytes, last modified: ',
                f.lastModifiedDate.toLocaleDateString(), '</li>');
  }
  document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}

function handleDragOver(evt) {
  evt.stopPropagation();
  evt.preventDefault();
  evt.dataTransfer.dropEffect = 'copy'; 
}

// イベントリスナーを設定
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);

ajax通信

requestの中身は{upload_file:(ファイルデータ)}のようなjson形式で表されます
サーバーサイド側でjson形式のデータのように扱えます

function file_upload()
{
    // フォームデータを取得
    let formdata = () => new FormData($('#my_form').get(0));
    // ファイルが未登録なら一番最初のファイルを追加
    // 複数ファイルアップロードの場合ここを修正
    if($('input[name="upload_file"]').val() == ""){
      formdata.append('upload_file',files[0])
    }

    //非同期通信
    $.ajax({
        url  : "/upload",
        type : "POST",
        data : formdata,
        cache       : false,
        contentType : false,
        processData : false,
        dataType: 'html',

    })
    .done(function(data, textStatus, jqXHR){
        console.log(data);
    })
    .fail(function(jqXHR, textStatus, errorThrown){
        console.log("fail");
    })
    .always(function(data){
        console.log("complete")
    });
}

flaskの場合は以下の記述で取り出せます

file = request.files['upload_file']

  • 他にもユーザー名等のパラメータがあった場合html上にinput要素を適宜追加してみてください

  • ちなみに複数ファイルの場合は
    {{upload_file1:(ファイル1), upload_file2:(ファイル2)}
    のような中身になります

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
35
Help us understand the problem. What are the problem?