17 Stimmen

Das Erkennen von Ordnern/Verzeichnissen in JavaScript-FileList-Objekten.

Ich habe kürzlich etwas Code zu Moodle beigetragen, der einige der Möglichkeiten von HTML5 nutzt, um das Hochladen von Dateien in Formularen per Drag & Drop vom Desktop aus zu ermöglichen (der Kern des Codes befindet sich hier: https://github.com/moodle/moodle/blob/master/lib/form/dndupload.js als Referenz).

Dies funktioniert gut, außer wenn ein Benutzer einen Ordner / Verzeichnis anstelle einer echten Datei zieht. Dann werden Mülldateien auf den Server hochgeladen, aber mit dem Dateinamen des Ordners.

Was ich suche, ist eine einfache und zuverlässige Möglichkeit, das Vorhandensein eines Ordners im Dateilisten-Objekt zu erkennen, damit ich ihn überspringen kann (und wahrscheinlich auch eine freundliche Fehlermeldung zurückgeben kann).

Ich habe die Dokumentation auf MDN durchsucht, sowie eine allgemeine Websuche gemacht, aber nichts gefunden. Ich habe auch die Daten in den Chrome-Entwicklertools durchgesehen und es scheint, dass der 'Typ' des Dateiobjekts konsistent auf "" für Ordner gesetzt ist. Ich bin jedoch nicht ganz überzeugt, dass dies die zuverlässigste Methode zur plattformübergreifenden Erkennung ist.

Hat jemand bessere Vorschläge?

25voto

gilly3 Punkte 83450

Sie können sich nicht auf file.type verlassen. Eine Datei ohne Erweiterung wird einen Typ von "" haben. Speichern Sie eine Textdatei mit einer .jpg Erweiterung und laden Sie sie in eine Dateisteuerung, dann wird ihr Typ als image/jpeg angezeigt. Und ein Ordner mit dem Namen "someFolder.jpg" wird auch als image/jpeg angezeigt.

Versuchen Sie stattdessen, das erste Byte der Datei zu lesen. Wenn Sie das erste Byte lesen können, haben Sie eine Datei. Wenn ein Fehler auftritt, haben Sie wahrscheinlich ein Verzeichnis:

try {
    await file.slice(0, 1).arrayBuffer();
    // es ist eine Datei!
}
catch (err) {
    // es ist ein Verzeichnis!
}

Wenn Sie bedauerlicherweise IE11 unterstützen müssen, wird die Datei nicht über die Methode arrayBuffer verfügen. Sie müssen auf das FileReader Objekt zurückgreifen:

// verwenden Sie diesen Code, wenn Sie IE11 unterstützen
var reader = new FileReader();
reader.onload = function (e) {
    // es ist eine Datei!
};
reader.onerror = function (e) {
    // es ist ein Verzeichnis!
};
reader.readAsArrayBuffer(file.slice(0, 1));

8voto

Nick G. Punkte 579

Ich bin auch auf dieses Problem gestoßen und unten ist meine Lösung. Grundsätzlich habe ich einen zweigleisigen Ansatz verfolgt:

(1) Überprüfe die Größe des Dateiobjekts und betrachte es als echte Datei, wenn es über 1MB groß ist (ich gehe davon aus, dass Ordner selbst nie so groß sind). (2) Wenn das Dateiobjekt kleiner als 1MB ist, lese ich es mit der Methode 'readAsArrayBuffer' von FileReader ein. Erfolgreiche Lesevorgänge rufen 'onload' auf und ich glaube, dass dies darauf hindeutet, dass es sich um eine echte Datei handelt. Fehlerhafte Lesevorgänge rufen 'onerror' auf und ich betrachte es als Verzeichnis. Hier ist der Code:

var isLikelyFile = null;
if (f.size > 1048576){ isLikelyFile = false; }
else{
    var reader = new FileReader();
    reader.onload = function (result) { isLikelyFile = true; };
    reader.onerror = function(){ isLikelyFile = false; };
    reader.readAsArrayBuffer(f);
}
//warten auf Abschluss des Lesevorgangs : sollte schnell sein, da Dateigröße < 1MB ;-)
var interval = setInterval(function() {
    if (isLikelyFile != null){
        clearInterval(interval);
        console.log('Überprüfung des Dateiobjekts abgeschlossen. isLikelyFile = ' + isLikelyFile);
    }
}, 100);

Ich habe dies in FF 26, Chrome 31 und Safari 6 getestet und drei Browser rufen 'onerror' auf, wenn sie versuchen, Verzeichnisse zu lesen. Lass mich wissen, wenn jemand einen Anwendungsfall kennt, bei dem dies fehlschlägt.

2voto

Richie Punkte 21

Ich schlage vor, FileReader.readAsBinaryString auf dem File-Objekt aufzurufen. In Firefox wird dies eine Ausnahme auslösen, wenn die Datei ein Verzeichnis ist. Ich mache dies nur, wenn die Datei den von gilly3 vorgeschlagenen Bedingungen entspricht.

Bitte sehen Sie sich meinen Blogbeitrag unter http://hs2n.wordpress.com/2012/08/13/detecting-folders-in-html-drop-area/ für weitere Details an.

Außerdem unterstützt jetzt Version 21 von Google Chrome das Ablegen von Ordnern. Sie können leicht überprüfen, ob die abgelegten Elemente Ordner sind, und auch deren Inhalte lesen.

Leider habe ich keine (clientseitige) Lösung für ältere Chrome-Versionen.

0voto

Brian Pipa Punkte 808

Ein weiterer Hinweis ist, dass der Typ bei jeder Datei mit einer unbekannten Erweiterung "" ist. Versuchen Sie, eine Datei mit dem Namen test.blah hochzuladen, und der Typ wird leer sein. UND... versuchen Sie, einen Ordner mit dem Namen test.jpg zu ziehen und abzulegen - der Typ wird auf "image/jpeg" gesetzt. Um zu 100% korrekt zu sein, können Sie sich nicht ausschließlich auf den Typ verlassen (oder wirklich überhaupt).

In meinen Tests hatten Ordner immer eine Größe von 0 (in FF und Chrome unter 64-Bit Windows 7 und unter Linux Mint (im Wesentlichen Ubuntu). Also überprüfe ich einfach, ob die Größe 0 beträgt, und es scheint in unserer Umgebung für mich zu funktionieren. Wir möchten auch keine 0-Byte-Dateien hochladen, also, wenn es 0 Byte sind, lautet die Meldung "Übersprungen - 0 Bytes (oder Ordner)".

0voto

Nam Nguyen Punkte 5440

Zur Information, dieser Beitrag wird Ihnen zeigen, wie Sie die dataTransfer API in Chrome verwenden, um den Dateityp zu erkennen: http://updates.html5rocks.com/2012/07/Drag-and-drop-a-folder-onto-Chrome-now-available

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X