HTML5s FileReader API lar klientnettleseren lese brukerens lokale filer, slik at den opplastede filen ikke lenger leses av serveren, noe som i stor grad reduserer belastningen på serveren og sparer tid som kreves for å laste opp filen. Men i praksis fant jeg ut at jeg lett kan håndtere en 300k loggfil med FileReader.readAsText(), men når loggfilen er så stor som 1G eller til og med 2G, krasjer nettleseren. Dette er fordi readAsText() laster målfilen inn i minnet samtidig, noe som får minnet til å overskride grensen. Så hvis nettapplikasjonen ofte må behandle store filer, bør vi bruke FileReader.readAsArrayBuffer() for å lese filene bit for bit.
Testscenario
Vårt scenario er enkelt, nemlig å bruke JavaScript for å hente tidsintervallet til en IIS-logg
Eksempler på IIS-logger:
#Software: Microsoft Internet Information Services 10.0 #Version: 1,0 #Date: 2016-08-18 06:53:55 #Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken 2016-08-18 06:53:55 ::1 GET / - 80 - ::1 Mozilla/5.0+(Windows+NT+10.0; +WOW64; +Trident/7.0; +rv:11.0)+like+Gecko - 200 0 0 476 2016-08-18 06:53:55 ::1 GET /iisstart.png - 80 - ::1 Mozilla/5.0+(Windows+NT+10.0; +WOW64; +Trident/7.0; +rv:11.0)+like+Gecko http://localhost/ 200 0 0 3 2016-08-18 08:45:34 10.172.19.198 GET /test/pac/wpad.dat - 80 - 10.157.21.235 Mozilla/5.0+(Windows+NT+6.1; +Win64; +x64; +Trident/7.0; +rv:11.0)+like+Gecko - 404 3 50 265 2016-08-18 08:46:44 10.172.19.198 GET /test/pac/wpad.dat - 80 - 10.157.21.235 Mozilla/5.0+(Windows+NT+6.1; +Win64; +x64; +Trident/7.0; +rv:11.0)+like+Gecko - 200 0 0 6 Målet vårt er å få tidsrammen for den loggen:
Starttid: 2016-08-18 06:53:55 Slutttid: 2016-08-18 08:46:44
Bruk readAsText()-implementasjon
Å bruke readAsText() er relativt enkelt, etter å ha hentet strengen til hele filen, hent de første 19 tegnene i hver linje fra starten, avgjør om datoformatet er oppfylt, hvis det er oppfylt, så er disse 19 tegnene starttidspunktet, og det samme går gjennom hver linje fra halen for å få slutttidspunktet, koden er som følger:
De løpende resultatene fra IIS-utvalget (størrelse: 1k) er som forventet.
Men når vi først har valgtEn større IIS-logg (størrelse: 2G) og nettleseren krasjer。 Grunnen er at readAsText() laster hele filen inn i minnet først, så hvis filen er for stor, vil det ikke være nok minne og nettleserprosessen vil krasje.
Bruk readAsArrayBuffer()-implementasjon
Siden File-objektet i JavaScript arver fra Blob, kan vi bruke Blob.slice()-metoden for å dele filen i små biter, og hovedideen er:
Først, ta de første 10 000 i innholdet i filen og konverter det til tekst Ta de første 19 tegnene i hver linje fra starten for å avgjøre om datoformatet er oppfylt, og hvis ja, er disse 19 tegnene starttidspunktet Deretter tar du de 10 000 innholdet på slutten av filen og konverterer det til tekst På samme måte, traverser hver linje fra haleinnholdet for å få slutttiden
Koden er som følger:
Ved å bruke readAsArrayBuffer() klarte vi å få de resultatene vi ønsket på svært kort tid, selv med mer enn 2G IIS-logger.
|