62 votes

Comment distinguer si un fichier ou un dossier est glissé avant d'être abandonné?

Je suis en train d'essayer de détecter si un dossier ou un fichier est déplacé dans les événements dragover ou dragenter.

Par exemple:

Dans le ondrop cas, il y a un argument, MouseEvent, avec un champ nommé dataTransfer, où sont répertoriés des fichiers ou des éléments (dépend du navigateur), et je peux définir ce que c'est pour Chrome ou Firefox.

Mais pour l' dragover et dragenter des événements de ces champs sont vides.

Note:

Pour les deux, des fichiers et des dossiers, dataTransfer.types est égal à "Fichiers". C'est, event.dataTransfer.types[i] == "Files" qui est vrai pour les dossiers et les fichiers.

J'ai besoin de cette information tout en la faisant glisser (dragover et dragenter événements), ne pas tomber.

Contexte De La Recherche

J'ai trouvé la suite d'un Débordement de Pile ajustement réponse pour ma question:

WebKit, et donc Chrome, est très restrictive sur quand vous pouvez appeler getData. Vous n'êtes pas autorisé à le faire à l'intérieur de dragstart ou dragover. Je pense que c'est la forme canonique de bug.

Mais cette réponse est à partir de 2012, et je ne trouve pas de réelle mise à jour de l'information.

Je suis à la recherche d'informations à jour sur ce.

109voto

Marco Bonelli Points 4003

Précisions sur le fichier drag/drop en HTML5

J'ai fait quelques recherches dans de nombreuses documentations pour ce sujet et testé par moi-même sur les différents navigateurs, c'est pourquoi j'ai décidé de résumer tout ce que je sais à propos de faire glisser et déposer des fichiers ici.

Glisser:

Lorsque vous faites glisser un fichier, vous pouvez utiliser certains auditeurs, tels que:

  • dragenter
  • dragover
  • dragend
  • dragleave

Étant donné que ce sont des drag événements, l' files de la propriété de l' event.dataTransfer ont length == 0 ou être vide (null). Donc vous ne pouvez pas lire les fichiers détails d'un événement glisser et vous ne pouvez pas vérifier s'ils sont les dossiers. Ce n'est pas un bug, c'est une mesure de sécurité. Imaginez que vous pouvez lire des fichiers sur un événement glisser: vous seriez capable de tout lire même si l'utilisateur ne veut pas télécharger des fichiers sur votre site. Il n'aurait aucun sens, au sérieux. Imaginez que vous faites glisser un fichier à partir de votre bureau à un autre dossier et que vous faites accidentellement glisser au travers d'une page web: la page web de lit de votre fichier et stocke vos informations personnelles sur son serveur... ce serait une grande confidentialité et la sécurité de la faute.

Toutefois, vous serez toujours en mesure de détecter si vous êtes déposer des fichiers par itération sur le tableau event.dataTransfer.types. Vous pouvez créer une fonction qui vérifie si l'événement glisser contient des fichiers, puis l'appeler dans le gestionnaire d'événements.

Exemple:

function containsFiles(event) {
    if (event.dataTransfer.types) {
        for (var i=0; i<event.dataTransfer.types.length; i++) {
            if (event.dataTransfer.types[i] == "Files") {
                return true;
            }
        }
    }

    return false;
}

function handleDragEnter(e) {
    e.preventDefault();
    if containsFiles(e) {
        // The drag event contains files
        // Do something
    } else {
        // The drag event doesn't contain files
        // Do something else
    }
}

Déposer:

Lorsque vous déposez un fichier dans la baisse de la div, vous utilisez un écouteur pour l'événement drop pour lire un fichier de propriétés telles que le nom, la taille, le type et la date de dernière modification.

Pour détecter si un fichier est un dossier, vous allez:

  1. Vérifiez si le fichier a type == "", parce que les dossiers ont pas de type.
  2. Vérifier si la taille du fichier est un multiple de 4096: size%4096 == 0, parce que les dossiers ont toujours une taille multiple de 4096 octets (ce qui est 4KiB).

Exemple:

function handleDrop(e) {
    e.stopPropagation();
    e.preventDefault();

    var files = e.dataTransfer.files;

    for (var i = 0, f; f = files[i]; i++) { // iterate in the files dropped
        if (!f.type && f.size%4096 == 0) {
            // The file is a folder
            // Do something
        } else {
            // The file is not a folder
            // Do something else
        }
    }
}

PROBLÈME CONNU: Depuis que les dossiers sont en fait des fichiers, c'est la seule façon de les distinguer d'un autre type de fichier. Bien que cette méthode ne vous donne pas la certitude absolue qu'un fichier est un dossier: il est peut-être un fichier sans extension et avec une taille de 0 ou N x 4096bytes.


Exemples:

Voici quelques exemples pour expliquer ce que j'ai dit ci-dessus:

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