【JavaScript】ドラッグ&ドロップでの画像アップロード機能(非同期処理)

JavaScriptとPHPを使用したファイルのアップロード機能を作成したので、処理内容を解説します。

処理はDrag & Drop API、Fetch API、Files APIを使用して実装し、非同期処理でサーバーサイドにデータを送信するまでの記述になります。

私が作成しているCMSでは3つの画像のアップロード処理を実装していますが、

・通常のファイル選択からのアップロード
・画像URLからイメージを取得してアップロード
・ドラッグ&ドロップで画像をアップロード

今回はドラッグ&ドロップで画像をアップロードする処理のみ解説します。(サーバーサイドの処理は別記事で解説します。)

これまでの記事で解説してきたAPIを実践的に使用していますので、復習を兼ねて細かくソースコードを追ってみてください。

ドラッグアンドドロップ で画像をアップロード

画面イメージ

アップロード画面は下記の画像のようなイメージです。CSSは記述しないので各自調整してください。

「ドラッグアンドドロップしてください」の枠内に選択した画像をドロップすると、サーバーサイドに画像データが送信されてデータベースに保存されます。

処理

HTML構造

<div class="right_form drag_form" id="dragAndDropArea">
 <p>ドラッグアンドドロップしてください</p>
</div>

JavaScript

ドラッグアンドドロップのJavaScriptの処理は

・イベント別のDOM操作 : Drag & Drop API(dragenter, dragover, dragleave, drop)のイベント別にDOM操作

・ファイルデータの取得 : ドロップされたイベントを起点にFiles APIを使用してファイルデータを取得

・サーバーサイドへの送信 : 取得したファイルデータをFormDataオブジェクトに格納してfetch()で送信

とやることが非常に多いです。それぞれの処理別に解説します。

イベント別のDOM操作

ドラッグアンドドロップ の処理を実行する際に、各イベント処理を用意します。さらに細かく指定することもできますがひとまず下記のイベント指定で問題なさそうです。

dragenter : ドラッグ中のファイルが、ドロップターゲットに入ったときに発生

dragover :  ドラッグ中のファイルが、ドロップターゲットの上にあるときに (数百ミリ秒間隔で) 発生

dragleave : ドラッグ中のファイルが妥当なドロップターゲットを離れたときに発生

drop : 妥当なドロップターゲットにドロップ(放たれたとき)に発生

JavaScript

// ドラッグ&ドロップのステータス dragenter, dragover中はtrueになる
let drag_over_status = false;

// ドラッグ要素にファイル画が入ってきたとき
$('#dragAndDropArea').on('dragenter', function(e) {
  e.stopPropagation();
  e.preventDefault();
  // dragenterのタイミングでドラッグ&ドロップ要素の枠線を目立たせる処理
  if(drag_over_status = true) $(this).addClass('dragover');
    //ドラッグ&ドロップのステータスをtrueにする
    drag_over_status = true;
});

// ドラッグ中
$('#dragAndDropArea').on('dragover', function(e) {
  e.stopPropagation();
  e.preventDefault();
  if(drag_over_status = true) return true;
    //ドラッグ&ドロップのステータスをtrueにする
    drag_over_status = true;
});

// ドラッグ要素から離れた時
$('#dragAndDropArea').on('dragleave', function(e) {
  e.stopPropagation();
  e.preventDefault();
  drag_over_status = false;
  // dragleaveのタイミングでドラッグ&ドロップ要素の枠線を通常に戻す
  $(this).removeClass('dragover');
});

// ドラッグされた時
$('#dragAndDropArea').on('drop', function(event) {
  event.stopPropagation();
  event.preventDefault();
  drag_over_status = false;
  // dropされたファイルを取得してアップロードする処理を実行
  create_upload_data(event);
});

ドラッグアンドドロップの処理を実装する際には、Drag & Drop APIを使用します。上記のそれぞれのイベント処理にpeventDefault, stopPropagationを記述していますが、これらは必要の記述であるため解説します。

この記事を読んでいる方に試してもらいたいのですが、画像を選択してブラウザ内にドロップしてみてください。ブラウザウィンドウで画像が開かれるはずです。ブラウザには何かがドロップされたときに行う動作がデフォルトで用意されています。index.htmlファイルをドロップしたら同じようにindex.htmlファイルが開きます。

ドラッグ&ドロップ機能を実装する際には、これらのデフォルトの動作を意図的に止めて、Drag & Drop APIの使用を明示的に示す必要があります。preventDefault()を記述しなければDrag & Drop APIを実行できないことから、記述する必要があります。

Drag & Drop APIによるDOM操作が実装できたら、create_upload_data(event);に処理を渡します。

ファイルデータの取得
// フォームデータの作成
function create_upload_data(event) {
  $('#dragAndDropArea').removeClass('dragover');
  drag_over_status = false;
  // FormDataオブジェクトの作成
  const formData = new FormData();
  // Files APIでdropされたファイルを取得
  const files = event.originalEvent.dataTransfer.files;
  // ファイルの数に応じてループ処理でFormDataにappendする
  for(let i = 0; i < files.length; i++) {
    formData.append('file', files[i]);
  }
   // アップロードする処理にFormDataを渡す
  upload_file_by_drop(formData);
}
サーバーサイドへの送信
// アップロード処理
function upload_file_by_drop(formData) {
// データを送信
fetch(コントローラーのURL(Path), {
  method: 'POST',
  body: formData,
})
// 成功したらレスポンステキストを取得
.then((response) => response.text())
// レスポンスを取得
.then((text) => {
  alert(text);
// エラー処理(例外処理)
.catch((error) => alert('画像のアップロードに失敗しました。'));
}

サーバーサイドにデータを送信した後は、PHP側での処理が必要ですが、少し長くなるので次回の記事で解説します。

フロントエンドとしては上記の処理でサーバーサイドにデータを送信できるので、試してみてください。

関連記事

■ Files APIについて : /javascript/files-api

■ FormDataオブジェクトについて : /javascript/formdata-create

■ 非同期処理について : /javascript/asynchronous-processing

■ fetch()について : /javascript/ajax-fetch

dragenter参考リンク :  https://developer.mozilla.org/ja/docs/Web/API/Document/dragenter_event

■ dragover参考リンク : https://developer.mozilla.org/ja/docs/Web/API/Document/dragover_event

■ dragleave参考リンク : https://developer.mozilla.org/ja/docs/Web/API/Document/dragleave_event

drop参考リンク : https://developer.mozilla.org/ja/docs/Web/API/Document/drop_event

この記事は役に立ちましたか?

もし参考になりましたら、下記のボタンで教えてください。

関連記事

コメント

この記事へのコメントはありません。