213 votes

Empêcher le navigateur de charger un fichier glissé-déposé

J'ajoute un téléchargeur html5 par glisser-déposer à ma page.

Lorsqu'un fichier est déposé dans la zone de téléchargement, tout fonctionne parfaitement.

Toutefois, si je dépose accidentellement le fichier en dehors de la zone de téléchargement, le navigateur charge le fichier local comme s'il s'agissait d'une nouvelle page.

Comment puis-je empêcher ce comportement ?

Gracias.

2 votes

Je suis juste curieux de savoir quel code vous utilisez pour gérer le téléchargement html5 par glisser/déposer. Merci.

0 votes

Le problème que vous rencontrez est dû à l'absence de e.dataTransfer() ou de preventDefault() sur les événements drop/dragenter/etc. Mais je ne peux pas le dire sans un exemple de code.

2voto

moe Points 2718

Essayez ceci :

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

2voto

Shannon Points 1579

Empêcher toutes les opérations de glisser-déposer par défaut n'est peut-être pas ce que vous souhaitez. Il est possible de vérifier si la source du glisser-déposer est un fichier externe, du moins dans certains navigateurs. J'ai inclus une fonction permettant de vérifier si la source du glisser-déposer est un fichier externe dans ce fichier. Réponse de StackOverflow .

En modifiant la réponse de Digital Plane, vous pourriez faire quelque chose comme ceci :

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);

1voto

scott_trinh Points 155

Pour compléter la méthode "vérifier la cible" décrite dans quelques autres réponses, voici une méthode plus générique/fonctionnelle :

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

Appelé comme ça :

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])
);

0voto

1.21 gigawatts Points 2457

J'ai un fichier HTML object ( embed ) qui remplit la largeur et la hauteur de la page. La réponse de @digital-plane fonctionne sur les pages web normales, mais pas si l'utilisateur tombe sur un objet incorporé. J'avais donc besoin d'une solution différente.

Si nous passons à l'utilisation du phase de capture des événements nous pouvons obtenir les événements avant que l'objet embarqué ne les reçoive (remarquez l'élément true à la fin de l'appel de l'écouteur d'événements) :

// 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);

En utilisant le code suivant (basé sur la réponse de @digital-plane), la page devient une cible de glisser, elle empêche les embeds d'objets de capturer les événements et charge ensuite nos images :

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);

Testé sur Firefox sur Mac.

0voto

hngr18 Points 305

J'utilise un sélecteur de classe pour les zones de téléchargement multiples. Ma solution a donc pris cette forme moins pure

Basé sur la réponse d'Axel Amthor, avec une dépendance à jQuery (alias $).

_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);
        });
    },

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X