webentwicklung-frage-antwort-db.com.de

Wie kann man erkennen, ob eine Datei oder ein Ordner vor dem Ablegen gezogen wird?

Ich versuche festzustellen, ob ein Ordner oder eine Datei in die EreignissedragoverNAME_oderdragenterNAME_gezogen wurde.

Zum Beispiel:

Im Ereignis ondropgibt es ein Argument mit dem Namen MouseEventname__, das ein Feld mit dem Namen dataTransferenthält, in dem je nach Browser Dateien (.files) oder Elemente (.items) aufgelistet sind. Das kann ich sowohl in Chrome als auch lesen Feuerfuchs . Für die Ereignisse dragoverund dragentersind diese Felder (.files und .items) jedoch leer. Das Problem ist, dass Ich benötige diese Informationen beim Ziehen und nicht beim Ablegen .

HINWEIS: Sowohl für Dateien als auch für Ordner lautet der event.dataTransfer.types[i] === "Files"truename__.

Hintergrundforschung

Ich fand die folgende Antwort teilweise passend für meine Frage:

WebKit und damit Chrome sind ziemlich restriktiv, wenn Sie getDataaufrufen können. Sie dürfen dies nicht innerhalb von dragstartoder dragovertun. Ich denke, das ist der kanonische Bug.

Diese Antwort stammt jedoch aus dem Jahr 2012 und Ich kann keine aktuellen Informationen zum Thema finden , daher suche ich nach aktuellen Informationen dazu.

53

TL; DR kann nicht :(

Wenn Sie sich fragen, warum diese Frage immer noch keine akzeptierte Antwort hat, können Sie lesen diese Meta-Frage, die vom OP erstellt wurde, und meine Antwort.

Datei dragdrop in HTML5

Ich habe in vielen Dokumentationen zu diesem Thema recherchiert und es in verschiedenen Browsern selbst getestet. Daher beschloss ich, alles, was ich über Drag & Drop von Dateien weiß, hier zusammenzufassen.

Ziehen

Wenn Sie eine Datei ziehen, können Sie einige Listener verwenden, z.

  • dragenter
  • dragover
  • dragend
  • dragleave

Da dies drag-Ereignisse sind, hat die files-Eigenschaft von event.dataTransfer entweder length == 0 oder ist leer (null).

Sie können nicht lesen Dateidetails in einem Ziehereignis und Sie prüfen kann nicht, ob es sich um Ordner handelt. Dies ist kein Fehler, es ist eine Sicherheitsmaßnahme.

Stellen Sie sich vor, Sie könnten Dateien bei einem Drag-Ereignis lesen: Sie könnten alles lesen, auch wenn der Benutzer keine Dateien auf Ihre Site hochladen möchte. Es würde keinen Sinn machen, ernsthaft. Stellen Sie sich vor, Sie ziehen eine Datei von Ihrem Desktop in einen anderen Ordner und ziehen sie versehentlich durch eine Webseite: Jetzt liest die Webseite Ihre Datei und speichert Ihre persönlichen Informationen auf dem Server ... _/das wäre ein riesiger Sicherheitsfehler.

Sie können jedoch immer noch feststellen, ob der Benutzer Dateien zieht (und unter Dateien meine ich auch Ordner, da Ordner Dateien sind) oder nicht, indem Sie über das Array event.dataTransfer.types iterieren. Sie können eine Funktion erstellen, die prüft, ob das Ziehereignis Dateien enthält, und es dann im Ereignishandler aufrufen.

Beispiel:

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

Ablegen

Wenn Sie eine Datei in das Drop <div> (oder in ein beliebiges Element, das Sie als Dropzone verwenden) ablegen, verwenden Sie einen Listener für das Ereignis drop, um einige Dateieigenschaften wie Name, Größe, Typ und Datum der letzten Änderung zu lesen.

Um herauszufinden, ob es sich bei einer Datei um einen Ordner handelt, gehen Sie folgendermaßen vor:

  1. Überprüfen Sie, ob die Datei type == "" enthält, da Ordner keinen Typ haben.
  2. Prüfen Sie, ob die Dateigröße ein Vielfaches von 4096 ist: size%4096 == 0, da Ordner immer ein Vielfaches von 4096 Byte (das sind 4 KB) sind.

Beispiel:

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

KNOWN ISSUE: Da es sich bei diesen Ordnern tatsächlich um Dateien handelt, ist dies die einzige Möglichkeit, sie von einer anderen Art von Datei zu unterscheiden. Diese Methode gibt Ihnen jedoch nicht die absolute Gewissheit, dass es sich bei einer Datei um einen Ordner handelt: Möglicherweise handelt es sich um eine Datei ohne Erweiterung mit einer Größe von 0 oder genau N x 4096B.


Arbeitsbeispiele

Hier einige Arbeitsbeispiele, um zu sehen, was ich oben in Aktion gesagt habe, und testen Sie es selbst. Vergewissern Sie sich vor dem Ausführen, dass Ihr Browser Drag & Drop-Funktionen unterstützt . Habe Spaß:

85
Marco Bonelli

Dies ist eine Funktion für das Löschen von Drop-Events (bitte beachten Sie, dass dies bei Dragover-Ereignissen nicht funktioniert)

isDraggedItemIsFile = function(e) {
// handle FF
if (e.originalEvent.dataTransfer.files.length == 0) {
    return false;
}
// handle Chrome
if (e.originalEvent.dataTransfer.items) {
    if (typeof (e.originalEvent.dataTransfer.items[0].webkitGetAsEntry) == "function") {
        return e.originalEvent.dataTransfer.items[0].webkitGetAsEntry().isFile;
    } else if (typeof (e.originalEvent.dataTransfer.items[0].getAsEntry) == "function") {
        return e.originalEvent.dataTransfer.items[0].getAsEntry().isFile;
    }
}
return true;
};

$forms.on('drop', function(e) {
        if (isDraggedItemIsFile(e)) {
            // do something if file
        } else{
           // is directory
        }
    });

Getestet mit FF V49, Chrome V55, Edge V25

0
Anas

Ich konnte den gesamten Mimetyp des Objekts, das gezogen wurde, über meine Seite ziehen. Der Mimetyp scheint für Ordner leer zu sein, sodass Sie ihn möglicherweise auf diese Weise unterscheiden können.

Teilcode (extrahiert aus React):

function handleDragOver(ev: DragEvent) {
    ev.preventDefault();
    ev.dataTransfer!.dropEffect = 'copy';
    console.log(Array.from(ev.dataTransfer.items).map(i => [i.kind,i.type].join('|')).join(', '));
}

document.addEventListener('dragover',handleDragOver);

Die Ausgabe sieht folgendermaßen aus:

file|image/x-icon, file|image/jpeg, file|application/vnd.ms-Excel

Wenn ich 3 Dateien über meine Seite ziehe.

Ich bin mir nicht sicher, ob es nur auf localhost funktioniert. Ich habe es noch nirgendwo hochgeladen, aber es funktioniert völlig.

MDN-Dokumente auf DataTransferItem

0
mpen

Sie können Dateien von Ordnern mit FileReader oder mit webkitGetAsEntry () trennen.

Das webkitGetAsEntry () wird von ie11 nicht unterstützt. Denken Sie daran!

Der Code wird wie folgt aussehen:

 onDrop(event) {
    let files = event.dataTransfer ? event.dataTransfer.files : 'null';

    for(let i = 0, file; file = files[i]; i++) {
       var reader = new FileReader();

       reader.onload = function (e) {
           console.log('it is a file!');
       };
       reader.onerror = function (e) {
          console.log('it is a folder!');
       };

       reader.readAsText(file);
    }

}
0