Erkennen von Ordnern/Verzeichnissen in den filelistischen JavaScript -Objekten
-
28-10-2019 - |
Frage
Ich habe kürzlich einen Code für Moodle beigetragen, der einige der Funktionen von HTML5 verwendet, damit Dateien in Formularen über Drag & Drop vom Desktop hochgeladen werden können (der Kernteil des Codes ist hier: https://github.com/moodle/moodle/blob/master/lib/form/dndupload.js als Referenz).
Dies funktioniert gut, außer wenn ein Benutzer schleppt a Ordner / Verzeichnis anstelle einer echten Datei. Der Müll wird dann auf den Server hochgeladen, aber mit dem Dateinamen, der dem Ordner entspricht.
Was ich suche, ist ein einfacher und zuverlässiger Weg dazu erkennen die Anwesenheit von a Mappe in dem Filelist Objekt, damit ich es überspringen kann (und wahrscheinlich auch eine freundliche Fehlermeldung zurückgeben).
Ich habe die Dokumentation zu MDN sowie eine allgemeinere Websuche durchgesehen, aber nichts aufgetaucht. Ich habe auch die Daten in den Chrome -Entwickler -Tools durchgesehen und es scheint, dass die 'Typ' des Dateiobjekts wird konsequent auf eingestellt "" Für Ordner. Ich bin jedoch nicht ganz davon überzeugt, dass dies die zuverlässigste Methode zur Erkennung von Cross-Browser ist.
Hat jemand bessere Vorschläge?
Lösung
Sie können sich nicht verlassen file.type
. Eine Datei ohne Erweiterung hat eine Art von Art von ""
. Speichern Sie eine Textdatei mit a .jpg
Erweiterung und laden Sie es in eine Dateisteuerung, und sein Typ wird als angezeigt image/jpeg
. Und ein Ordner namens "seltsfolder.jpg" wird auch seinen Typ haben als image/jpeg
.
Versuchen Sie, die Datei mit a zu lesen FileReader
. Wenn ein Verzeichnis hineingezogen wird, die FileReader
wird die erhöhen error
Veranstaltung:
var reader = new FileReader();
reader.onload = function (e) {
// it's a file
};
reader.onerror = function (e) {
// it's a directory
};
reader.readAsText(file);
Glücklicherweise, in IE11, wenn ein Verzeichnis fallen gelassen wird, ist das e.dataTransfer.files
Die Sammlung ist leer.
Chrom enthüllt eine zusätzliche Immobilie in e.dataTransfer
genannt items
enthält eine Sammlung von DataTransferItem
Objekte. Bei jedem dieser Objekte können Sie anrufen item.webkitGetAsEntry()
, was zurückgibt und Entry
Objekt. Das Entry
Objekt hat Eigenschaften isDirectory
und isFile
:
// Chrome only
if (e.dataTransfer.items && e.dataTransfer.items.length) {
[].forEach.call(e.dataTransfer.items, function(item) {
var entry = item.webkitGetAsEntry();
if (entry && entry.isFile) {
var file = item.getAsFile(); // same as object in e.dataTransfer.files[]
// do something with the file
}
}
}
Interessanterweise hat in meinem Experimentieren jeder Ordner, den ich mir angesehen habe File.size % 4096
als Null. Natürlich werden dies auch einige Dateien haben. File.size
ist kein zuverlässiger Indikator dafür, ob eine Datei tatsächlich ein Ordner ist.
Andere Tipps
Ich bin auch auf dieses Problem gestoßen und unten ist meine Lösung. Grundsätzlich habe ich einen zweizehnten Ansatz gewählt:
(1) Überprüfen Sie, ob die Größe des Dateiobjekts groß ist, und betrachten Sie es als eine echte Datei, wenn sie über 1 MB ist (ich gehe davon aus, dass Ordner selbst nie so groß sind).(2) Wenn das Dateiobjekt kleiner als 1 MB ist, habe ich es mit der Methode "ReadasArrayBuffer" von FileReader gelesen. Erfolgreiche Reads Call "Onload" und ich glaube, dies zeigt an, dass das Dateiobjekt eine echte Datei ist. Fehlgeschlagenen Leads Call "OnError" 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);
}
//wait for reader to finish : should be quick as file size is < 1MB ;-)
var interval = setInterval(function() {
if (isLikelyFile != null){
clearInterval(interval);
console.log('finished checking File object. isLikelyFile = ' + isLikelyFile);
}
}, 100);
Ich habe dies in FF 26, Chrome 31 und Safari 6 und drei Browsern getestet, die "OnError" nennen, wenn ich versuchte, Verzeichnisse zu lesen. Lassen Sie mich wissen, ob jemand an einen Anwendungsfall denken kann, in dem dies fehlschlägt.
Ich schlage an, Anrufe anzurufen FileReader.readAsBinaryString
auf der File
Objekt. In Firefox wird dies eine Ausnahme hervorrufen, wenn die File
ist ein Directory
. Ich mache das nur, wenn die File
erfüllt die von Gilly3 vorgeschlagenen Bedingungen.
Bitte beachten Sie meinen Blog -Beitrag unter http://hs2n.wordpress.com/2012/08/13/detecting-folter-in-html------L-Lop-area/ für mehr Details.
Außerdem unterstützt Version 21 von Google Chrome jetzt Ablagerungsordner. Sie können leicht prüfen, ob es sich bei den fallengelassenen Elementen um Ordner handelt, und auch deren Inhalt lesen.
Leider habe ich keine (clientseitige) Lösung für ältere Chromversionen.
Ein weiterer Hinweis ist, dass der Typ "" für jede Datei mit einer unbekannten Erweiterung ist. Versuchen Sie, eine Datei mit dem Namen test.blah hochzuladen und der Typ ist leer. Und ... versuchen Sie, einen Ordner mit dem Namen test.jpg zu ziehen und zu fallen. Um 100% korrekt zu sein, können Sie sich nicht nur auf Typ verlassen (oder wenn überhaupt).
Bei meinen Tests waren die Ordner schon immer Größe 0 (auf FF und Chrom auf 64-Bit-Windows 7 und unter Linux Mint (Ubuntu im Wesentlichen). Also prüft meine Ordnerprüfung nur, ob die Größe 0 ist und es für mich zu funktionieren scheint In unserer Umgebung. Wir möchten auch nicht, dass 0 -Byte -Dateien hochgeladen werden. Wenn es 0 Byte ist, kommt die Nachricht als "übersprungen - 0 Bytes (oder Ordner) zurück".
Zu Ihrer Information, in diesem Beitrag wird erfahren, wie Sie die Datatransfer -API in Chrome verwenden, um den Dateityp zu erkennen: http://updates.html5rocks.com/2012/07/drag-and-drop-afolder-onto-crome-now-available