Domanda

Di recente ho contribuito a Moodle che utilizza alcune delle capacità di HTML5 per consentire la caricamento dei file nei moduli tramite trascinamento dal desktop (la parte principale del codice è qui: https://github.com/moodle/moodle/blob/master/lib/form/dndupload.js per riferimento).

Funziona bene, tranne quando un utente trascina un cartella / directory invece di un vero file. La spazzatura viene quindi caricata sul server, ma con il nome file corrisponde alla cartella.

Quello che sto cercando è un modo facile e affidabile rilevare la presenza di a cartella nel Filelista oggetto, quindi posso saltarlo (e probabilmente restituire anche un messaggio di errore amichevole).

Ho esaminato la documentazione su MDN, oltre a una ricerca web più generale, ma non ho alzato nulla. Ho anche esaminato i dati negli strumenti di sviluppatore Chrome e sembra che il 'genere' dell'oggetto file è costantemente impostato su "" per le cartelle. Tuttavia, non sono del tutto convinto che questo sia il metodo di rilevamento del browser più affidabile.

Qualcuno ha qualche suggerimento migliori?

È stato utile?

Soluzione

Non puoi fare affidamento file.type. Un file senza estensione avrà un tipo di "". Salva un file di testo con a .jpg estensione e caricarlo in un controllo del file e il suo tipo verrà visualizzato come image/jpeg. E, una cartella chiamata "somefolder.jpg" avrà anche il suo tipo come image/jpeg.

Prova a leggere il file con a FileReader. Se una directory viene trascinata, il FileReader aumenterà il error evento:

var reader = new FileReader();
reader.onload = function (e) {
    // it's a file
};
reader.onerror = function (e) {
    // it's a directory
};
reader.readAsText(file);

Fortunatamente, in IE11, quando una directory viene lasciata cadere, il e.dataTransfer.files La collezione è vuota.

Chrome espone una proprietà aggiuntiva in e.dataTransfer chiamato items contenente una raccolta di DataTransferItem oggetti. Su ciascuno di questi oggetti, puoi chiamare item.webkitGetAsEntry(), che restituisce un Entry oggetto. Il Entry L'oggetto ha proprietà isDirectory e 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
      }
   }
}

È interessante notare, nella mia sperimentazione, ogni cartella che ho visto ha avuto File.size % 4096 come zero. Tuttavia, ovviamente, anche alcuni file avranno questo. File.size non è un indicatore affidabile del fatto che un file sia effettivamente una cartella.

Altri suggerimenti

Ho anche incontrato questo problema e di seguito è la mia soluzione. Fondamentalmente, ho adottato un approccio a due pronge:

(1) Controlla se la dimensione dell'oggetto file è grande e considera che sia un file autentico se è superiore a 1 MB (presumo che le cartelle stesse non siano mai così grandi).(2) Se l'oggetto file è inferiore a 1 MB, l'ho letto usando il metodo "ReadasArrayBuffer" di FileReader. Le letture di successo si chiama "Onload" e credo che questo indichi che l'oggetto file sia un file autentico. Non riuscito legge la chiamata "Onerror" e lo considero una directory. Ecco il codice:

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);

Ho testato questo in FF 26, Chrome 31 e Safari 6 e tre browser chiamano "Onerror" quando ho tentato di leggere le directory. Fammi sapere se qualcuno può pensare a un caso d'uso in cui questo fallisce.

Propongo di chiamare FileReader.readAsBinaryString sul File oggetto. In Firefox, questo aumenterà un'eccezione quando il File è un Directory. Lo faccio solo se il File soddisfa le condizioni proposte da Gilly3.

Si prega di consultare il mio post sul blog su http://hs2n.wordpress.com/2012/08/13/decting-forters-in-html-drop-area/ per ulteriori dettagli.

Inoltre, la versione 21 di Google Chrome ora supporta le cartelle di caduta. Puoi facilmente verificare se gli elementi lasciati cadere sono cartelle e leggi anche il loro contenuto.

Sfortunatamente, non ho alcuna soluzione (lato client) per versioni di Chrome più vecchie.

Un'altra nota è che il tipo è "" per qualsiasi file che abbia un'estensione sconosciuta. Prova a caricare un file denominato test.blah e il tipo sarà vuoto. E ... prova a trascinare e far cadere una cartella denominata test.jpg: il tipo verrà impostato su "Image/JPEG". Per essere corretti al 100%, non puoi dipendere dal tipo esclusivamente (o se non del tutto).

Nei miei test, le cartelle sono sempre state di dimensioni 0 (su FF e Chrome su Windows 7 a 64 bit e sotto Linux Mint (Ubuntu essenzialmente). Quindi, il mio controllo delle cartelle è solo verificare se la dimensione è 0 e mi sembra funzionare per me Nel nostro ambiente. Inoltre, non vogliamo che i file 0 byte siano stati caricati, quindi se è 0 byte il messaggio ritorna come "saltato - 0 byte (o cartella)"

FYI, questo post ti dirà come utilizzare API DataTransfer in Chrome per rilevare il tipo di file: http://updates.html5rocks.com/2012/07/drag-and-drop-a-folder-onto- chrome-now-vailable

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top