readas - read file javascript




Ripetendo i file per FileReader, l'output contiene sempre l'ultimo valore del loop (2)

Sto usando l'API FileReader per leggere i file sul locale.

<input type="file" id="filesx" name="filesx[]" onchange="readmultifiles(this.files)" multiple="" />

<script>
function readmultifiles(files) {
    var ret = "";
    var ul = document.querySelector("#bag>ul");
    while (ul.hasChildNodes()) {
        ul.removeChild(ul.firstChild);
    }
    for (var i = 0; i < files.length; i++)  //for multiple files
    {
        var f = files[i];
        var name = files[i].name;
        alert(name);
        var reader = new FileReader();  
        reader.onload = function(e) {  
            // get file content  
            var text = e.target.result;
            var li = document.createElement("li");
            li.innerHTML = name + "____" + text;
            ul.appendChild(li);
        }
        reader.readAsText(f,"UTF-8");
    }
}
</script>

Se l'input include 2 file:

file1 ---- "content1"
file2 ---- "content2"

Ottengo questo risultato:

file2__content1
file2__content2

Come risolvere il codice da visualizzare:

file1__content1
file2__content2

Anche se non è esattamente robusto o a prova di futuro, vale la pena ricordare che questo può essere ottenuto anche aggiungendo una proprietà all'oggetto FileReader :

var reader = new FileReader();
reader._NAME = files[i].name; // create _NAME property that contains filename.

Quindi accedervi tramite e all'interno della funzione di callback onload :

li.innerHTML = e.target._NAME + "____" + text;


Perché questo funziona:

Anche se la variabile del reader viene sostituita più volte durante il ciclo come i , il new FileReader oggetto new FileReader è unico e rimane in memoria. È accessibile all'interno della funzione reader.onload tramite l'argomento e . Memorizzando ulteriori dati nell'oggetto di reader , viene tenuto in memoria e accessibile tramite reader.onload tramite argomento evento e.target .

Questo spiega perché il tuo output è:

file2 __content1
file2__content2

e non:

file1__content1
file2__content2

Il contenuto viene visualizzato correttamente perché e.target.result è una proprietà all'interno dell'oggetto FileReader stesso . FileReader aveva contenuto una proprietà nome file per impostazione predefinita, avrebbe potuto essere utilizzato e questo intero pasticcio evitato del tutto.


Una parola di cautela

Questo è chiamato estendere gli oggetti host (se capisco la differenza tra gli oggetti nativi ...). FileReader è l'oggetto host che viene esteso in questa situazione. Molti sviluppatori professionisti credono che farlo sia una cattiva pratica e / o un male. Le collisioni possono verificarsi se _NAME viene utilizzato in futuro. Questa funzionalità non è documentata in alcuna specifica, quindi potrebbe anche rompersi in futuro, e potrebbe non funzionare nei browser più vecchi.

Personalmente, non ho riscontrato problemi aggiungendo proprietà aggiuntive agli oggetti host. Supponendo che il nome della proprietà sia abbastanza unico, i browser non lo disabilitano, e i browser futuri non cambiano troppo questi oggetti, dovrebbe funzionare bene.

Ecco alcuni articoli che spiegano questo abbastanza bene:

http://kendsnyder.com/extending-host-objects-evil-extending-native-objects-not-evil-but-risky/
http://perfectionkills.com/whats-wrong-with-extending-the-dom/

E qualche articolo sul problema stesso:

http://tobyho.com/2011/11/02/callbacks-in-loops/


Ho avuto lo stesso problema, l'ho risolto usando Array.from

let files = e.target.files || e.dataTransfer.files;

Array.from(files).forEach(file => {
 // do whatever
})