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?

War es hilfreich?

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top