Vähän ongelmia tiedostojen lukemisessa omalta koneelta www-sivulle javascriptillä.
FileReader rajapinnassa on onload -määritys, jossa parametrina tulee tiedot ladattavasta tiedostosta mm. nimi
Toisaalta on määritetty myös onprogress -metodi, jonka avulla voi monitoroida latauksen etenemistä.
Ongelma; Jos ladataan useita tiedostoja yhdellä valinnalla (<input/> - multiple attribuutti), onprogress-metodi ei tiedä, mitä tiedostoa ollaan lataamassa. Sille välitetään progressevent -tyyppinen parametri, jossa ei ole muuta informaatiota kuin latauksen suuruus ja ladattu tavumäärä.
Tarkoituksena olisi tehdä kullekin ladattavalle tiedostolle oma editysmislaatikko, jota päivitetään sitä mukaa kuin lataus etenee. Koska onprogress -metodi ei tiedä, mitä tiedostoa lataus koskee, ei siis oikean edistymislaatikon päivitys onnistu.
Eikö FileReader lue vain yhtä tiedostoa kerralla? Sinulla pitäisi siis olla jokaiselle tiedostolle oma FileReader. Alla on yksinkertainen esimerkki.
<!DOCTYPE html> <meta charset="UTF-8" /> <style> dd { font-family: monospace; } </style> <script> function load(f) { var dl = document.getElementById("output"), dt, dd_bar, dd_bytes; dl.appendChild(dt = document.createElement("dt")); dl.appendChild(dd_bar = document.createElement("dd")); dl.appendChild(dd_bytes = document.createElement("dd")); dt.textContent = f.name; dd_bar.textContent = "[LOADING]"; dd_bytes.textContent = "? / ? bytes"; var reader = new FileReader(); reader.onprogress = function(e) { var x = Math.round(20 * e.loaded / e.total); dd_bar.textContent = "[" + "#".repeat(x) + ".".repeat(20-x) + "]"; dd_bytes.textContent = e.loaded + " / " + e.total + " bytes"; }; reader.onload = function() { dd_bar.textContent = "READY"; }; reader.onerror = function() { dd_bar.textContent = "ERROR"; }; reader.onabort = function() { dd_bar.textContent = "ABORTED"; }; reader.readAsBinaryString(f); } function handle(files) { for (var i = 0; i < files.length; ++i) { load(files[i]); } } </script> <input type="file" multiple="multiple" onchange="handle(this.files)" /> <dl id="output"></dl>
”Lukeminen www-sivulle” tarkoittaa vasta tiedoston avaamista levyltä selaimen muistiin eikä suinkaan tiedoston siirtämistä palvelimelle, joten tavallaan edistymislaatikko on aika turha: pienet tiedostot aukeavat joka tapauksessa hetkessä.
Lukee, mutta loopissa, jossa tiedostot käsitellään, jokaiselle tiedostoon liitetään oma Filereader
Mallikoodisi ei lue kuin yhden tiedoston, vaikka olisi valittu koko leegio
function readMultipleFiles(evt) { var files = evt.target.files; if (files) { for (var i=0, f; f=files[i]; i++) { var r = new FileReader(); r.onloadend = function(e) {...} r.onload = (function(f) {...} r.onprogress = function(e) {...} r.readAsDataURL(f); }
Ongelma on ilmeinen.
Mallikoodini lukee kaikki tiedostot. Lue koodi kunnolla ja kokeile edes.
Virheesi on ilmeinen: et osaa perussääntöjä siitä, miten muuttujat sidotaan nimettömiin funktioihin, ja päädyt tekemään monta identtistä funktiota, joihin on sidottu samat muuttujat (i ja f), joiden arvot muuttuvat silmukan aikana. Juuri tämän takia silmukan sisältö pitää laittaa erilliseen funktioon. Toinen vaihtoehto on lisätä FileReader-olioon omia ominaisuuksia, jotka löytyvät tapahtumankäsittelijässä this-objektista.
Kiva asenne! Kiitos kuitenkin. Yritetään. Tämä javascript on kyllä yksi painajainen :)
ilkkak kirjoitti:
Kiva asenne!
Tervetuloa Ohjelmointiputkaan! Asiallisemmat keskustelut Stack Overflowssa.
(Ennustus: tämä viesti tullaan poistamaan aika nopeasti :D)
Aihe on jo aika vanha, joten et voi enää vastata siihen.