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.

340voto

Digital Plane Points 11741

Vous pouvez ajouter un écouteur d'événements à la fenêtre qui appelle preventDefault() sur tous les événements de type "glisser-déposer".
Exemple :

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

52 votes

Dragover est la pièce qui me manquait.

13 votes

Je confirme que les deux dragover y drop sont nécessaires pour empêcher le navigateur de charger le fichier déposé. (Chrome latest 2015/08/03). La solution fonctionne aussi sur FF latest.

5 votes

Cela fonctionne parfaitement, et je peux confirmer qu'il peut être utilisé en combinaison avec des éléments de page qui sont configurés pour accepter les événements de dépôt, tels que ceux des scripts de téléchargement de fichiers par glisser-déposer comme resumable.js. Il est utile d'empêcher le comportement par défaut du navigateur dans les cas où un utilisateur dépose accidentellement un fichier qu'il veut télécharger en dehors de la zone de dépôt de téléchargement de fichier, et se demande ensuite pourquoi il voit maintenant ce même fichier rendu directement dans la fenêtre du navigateur (en supposant qu'un type de fichier compatible comme une image ou une vidéo a été déposé), plutôt que le comportement attendu de voir leur fichier téléchargé.

43voto

Axel Amthor Points 9526

Après avoir beaucoup bricolé, j'ai trouvé que c'était la solution la plus stable :

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>

Réglage des deux effectAllow y dropEffect inconditionnellement sur la fenêtre fait que ma zone de dépôt n'accepte plus aucun d-n-d, que les propriétés soient nouvelles ou non.

9voto

Davidos Krausos Points 449

Pour permettre le glisser-déposer uniquement sur certains éléments, vous pourriez faire quelque chose comme :

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

0 votes

Cela fonctionne parfaitement pour moi, mais j'ajouterais également la vérification du type=file, sinon vous pouvez toujours glisser vers les entrées de texte.

9voto

VisioN Points 62518

Pour jQuery, la bonne réponse sera :

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

Ici return false se comportera comme event.preventDefault() y event.stopPropagation() .

4voto

Superole Points 401

Note : Bien que l'OP n'ait pas demandé une solution Angular, je suis venu ici pour la chercher. C'est donc pour partager ce que j'ai trouvé être une solution viable, si vous utilisez Angular.

D'après mon expérience, ce problème se pose d'abord lorsque vous ajoutez la fonctionnalité de dépôt de fichiers à une page. Par conséquent, je pense que le composant qui ajoute cette fonctionnalité doit également être responsable de la prévention du dépôt en dehors de la zone de dépôt.

Dans ma solution, la zone de dépôt est une entrée avec une classe, mais tout sélecteur non ambigu fonctionne.

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';
    }
  }
}

Les écouteurs sont ajoutés/supprimés automatiquement lorsque le composant est créé/détruit, et les autres composants utilisant la même stratégie sur la même page n'interfèrent pas entre eux grâce à la fonction stopPropagation().

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