ブラウザーがドラッグアンドドロップされたファイルを読み込まないようにする


194

私のページにhtml5ドラッグアンドドロップアップローダーを追加しています。

ファイルがアップロード領域にドロップされると、すべてがうまく機能します。

ただし、誤ってファイルをアップロード領域の外にドロップすると、ブラウザはローカルファイルを新しいページのようにロードします。

この動作を防ぐにはどうすればよいですか?

ありがとう!


2
HTML5ドラッグ/ドロップアップロードを処理するために使用しているコードに興味があるだけです。ありがとう。
robertwbradford 2011

あなたが持っている問題は、e.dataTransfer()が欠落しているか、drop / dragenter / etcにpreventDefault()が欠落していることが原因です。イベント。しかし、コードサンプルがないとわかりません。
HoldOffHunger 2018

回答:


312

preventDefault()すべてのドラッグオーバーイベントとドロップイベントを呼び出すイベントリスナーをウィンドウに追加できます。
例:

window.addEventListener("dragover",function(e){
  e = e || event;
  e.preventDefault();
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
},false);

44
ドラッグオーバーは私が欠けていた部分です。
cgatian 2014

11
ブラウザがドロップされたファイルをロードしないようにするには、dragoverdropハンドラの両方が必要であることを確認しました。(Chrome最新2015/08/03)。ソリューションはFF最新でも動作します。
Offirmo

4
これは完全に機能し、ドロップイベントを受け入れるように構成されているページ要素(resumable.jsなどのドラッグアンドドロップファイルアップロードスクリプトからのものなど)と組み合わせて使用​​できることを確認できます。ユーザーが実際にアップロードしたいファイルを実際のファイルアップロードドロップゾーンの外に誤ってドロップした場合に、ブラウザーのデフォルトの動作を防止して、同じファイルがブラウザーウィンドウに直接表示されるのを不思議に思うのは便利です(画像やビデオなどの互換性のあるファイルタイプが削除されたと想定した場合)、ファイルのアップロードを表示するという予想される動作ではありません。
bluebinary 16

15
注:これにより、へのファイルのドラッグも無効になります<input type="file" />。がe.targetファイル入力かどうかを確認し、そのようなイベントを通過させる必要があります。
Sebastian Nowak

6
何 ?ウィンドウのドラッグオーバーでファイルをロードする必要があるのはなぜですか?これは意味がありません...
L.Trabacchin

37

何度もいじった後、これが最も安定した解決策であることがわかりました:

var dropzoneId = "dropzone";

window.addEventListener("dragenter", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
}, false);

window.addEventListener("dragover", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
});

window.addEventListener("drop", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
});
<div id="dropzone">...</div>

ウィンドウで無条件に両方effectAllowを設定するとdropEffect、プロパティが新規に設定されているかどうかに関係なく、ドロップゾーンがdndを受け入れなくなります。


e.dataTransfer()は、この作業を行うための重要な要素であり、「受け入れられた回答」では言及できませんでした。
HoldOffHunger 2018

9

jQueryの場合、正しい答えは次のとおりです。

$(document).on({
    dragover: function() {
        return false;
    },
    drop: function() {
        return false;
    }
});

ここでreturn falseevent.preventDefault()およびとして動作しevent.stopPropagation()ます。


9

一部の要素でのみドラッグアンドドロップを許可するには、次のようにします。

window.addEventListener("dragover",function(e){
  e = e || event;
  console.log(e);
  if (e.target.tagName != "INPUT") { // check which element is our target
    e.preventDefault();
  }
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  console.log(e);
  if (e.target.tagName != "INPUT") {  // check which element is our target
    e.preventDefault();
  }  
},false);

私にはぴったりですが、type = fileのチェックも追加します。それ以外の場合は、テキスト入力にドラッグできます
Andreas Zwerger

2

これを試して:

document.body.addEventListener('drop', function(e) {
    e.preventDefault();
}, false);

2

デフォルトですべてのドラッグアンドドロップ操作を防止することは、望ましくない場合があります。少なくとも一部のブラウザでは、ドラッグソースが外部ファイルであるかどうかを確認できます。このStackOverflowの回答には、ドラッグソースが外部ファイルであるかどうかを確認する関数が含まれています

Digital Planeの答えを変更すると、次のようなことができます。

function isDragSourceExternalFile() {
     // Defined here: 
     // https://stackoverflow.com/a/32044172/395461
}

window.addEventListener("dragover",function(e){
    e = e || event;
    var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer);
    if (IsFile) e.preventDefault();
},false);
window.addEventListener("drop",function(e){
    e = e || event;
    var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer);
    if (IsFile) e.preventDefault();
},false);

1
のポイントはe || event;何ですか?どこがevent定義されていますか?気にしないで。IEのグローバルオブジェクトのようですか?私はこの見積もりを"In Microsoft Visual Basic Scripting Edition (VBScript), you must access the event object through the window object." ここで
1.21ギガワット2017年

2

注: OPはAngularソリューションを要求しませんでしたが、私はそれを探してここに来ました。したがって、これは、Angularを使用している場合に、私が実行可能なソリューションであることがわかったものを共有することです。

私の経験では、この問題は最初にファイルドロップ機能をページに追加したときに発生します。したがって、私の意見では、これを追加するコンポーネントは、ドロップゾーンの外へのドロップを防ぐ役割も果たす必要があります。

私の解決策では、ドロップゾーンはクラスの入力ですが、明確なセレクターは機能します。

import { Component, HostListener } from '@angular/core';
//...

@Component({
  template: `
    <form>
      <!-- ... -->
      <input type="file" class="dropzone" />
    </form>
  `
})
export class MyComponentWithDropTarget {

  //...

  @HostListener('document:dragover', ['$event'])
  @HostListener('drop', ['$event'])
  onDragDropFileVerifyZone(event) {
    if (event.target.matches('input.dropzone')) {
      // In drop zone. I don't want listeners later in event-chain to meddle in here
      event.stopPropagation();
    } else {
      // Outside of drop zone! Prevent default action, and do not show copy/move icon
      event.preventDefault();
      event.dataTransfer.effectAllowed = 'none';
      event.dataTransfer.dropEffect = 'none';
    }
  }
}

コンポーネントが作成または破棄されると、リスナーは自動的に追加または削除されます。同じページで同じ戦略を使用する他のコンポーネントは、stopPropagation()によって互いに干渉しません。


これは魅力のように機能します!! ブラウザーは禁止アイコンを追加してマウスカーソルを変更することもできます。
pti_jul

1

他のいくつかの回答で概説されている「ターゲットのチェック」方法に基づいて構築するために、より一般的で機能的な方法を次に示します。

function preventDefaultExcept(predicates) {
  return function (e) {
    var passEvery = predicates.every(function (predicate) { return predicate(e); })
    if (!passEvery) {
      e.preventDefault();
    }
  };
}

次のように呼び出されます:

function isDropzone(e) { return e.target.id === 'dropzone'; }
function isntParagraph(e) { return e.target.tagName !== 'p'; }

window.addEventListener(
  'dragover',
  preventDefaultExcept([isDropzone, isntParagraph])
);
window.addEventListener(
  'drop',
  preventDefaultExcept([isDropzone])
);

また、ここにES6を追加することもできますfunction preventDefaultExcept(...predicates){}。そして、それを次のように使用しますpreventDefaultExcept(isDropzone, isntParagraph)
hlfrmn

0

ページの幅と高さを満たすHTML objectembed)があります。@ digital-planeによる回答は通常のWebページで機能しますが、ユーザーが埋め込みオブジェクトにドロップした場合は機能しません。したがって、別のソリューションが必要でした。

イベントキャプチャフェーズの使用に切り替えると、埋め込みオブジェクトがイベントを受け取る前にイベントを取得できます(trueイベントリスナー呼び出しの最後の値に注意してください)。

// document.body or window
document.body.addEventListener("dragover", function(e){
  e = e || event;
  e.preventDefault();
  console.log("over true");
}, true);

document.body.addEventListener("drop", function(e){
  e = e || event;
  e.preventDefault();
  console.log("drop true");
}, true);

次のコード(@ digital-planeの回答に基づく)を使用すると、ページがドラッグターゲットになり、オブジェクトの埋め込みがイベントをキャプチャして画像を読み込まないようにします。

document.body.addEventListener("dragover", function(e){
  e = e || event;
  e.preventDefault();
  console.log("over true");
}, true);

document.body.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
  console.log("Drop true");

  // begin loading image data to pass to our embed
  var droppedFiles = e.dataTransfer.files;
  var fileReaders = {};
  var files = {};
  var reader;

  for (var i = 0; i < droppedFiles.length; i++) {
    files[i] = droppedFiles[i]; // bc file is ref is overwritten
    console.log("File: " + files[i].name + " " + files[i].size);
    reader = new FileReader();
    reader.file = files[i]; // bc loadend event has no file ref

    reader.addEventListener("loadend", function (ev, loadedFile) {
      var fileObject = {};
      var currentReader = ev.target;

      loadedFile = currentReader.file;
      console.log("File loaded:" + loadedFile.name);
      fileObject.dataURI = currentReader.result;
      fileObject.name = loadedFile.name;
      fileObject.type = loadedFile.type;
      // call function on embed and pass file object
    });

    reader.readAsDataURL(files[i]);
  }

}, true);

Mac上のFirefoxでテスト済み。


0

私は複数のアップロード領域にクラスセレクターを使用しているので、私のソリューションはこのあまり純粋でない形式を取っていました

Axel Amthorの回答に基づき、jQueryに依存(別名$)

_stopBrowserFromOpeningDragAndDropPDFFiles = function () {

        _preventDND = function(e) {
            if (!$(e.target).is($(_uploadBoxSelector))) {
                e.preventDefault();
                e.dataTransfer.effectAllowed = 'none';
                e.dataTransfer.dropEffect = 'none';
            }
        };

        window.addEventListener('dragenter', function (e) {
            _preventDND(e);
        }, false);

        window.addEventListener('dragover', function (e) {
            _preventDND(e);
        });

        window.addEventListener('drop', function (e) {
            _preventDND(e);
        });
    },
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.