HTML5's FileReader API tillader klientbrowseren at læse brugerens lokale filer, så den uploadede fil ikke længere læses af serveren, hvilket i høj grad reducerer byrden på serveren og sparer den tid, det tager at uploade filen. Men i praksis fandt jeg ud af, at jeg nemt kan håndtere en 300k logfil med FileReader.readAsText(), men når logfilen er så stor som 1G eller endda 2G, crasher browseren. Dette skyldes, at readAsText() indlæser målfilen i hukommelsen på én gang, hvilket får hukommelsen til at overskride grænsen. Så hvis webapplikationen ofte skal behandle store filer, bør vi bruge FileReader.readAsArrayBuffer() til at læse filerne stykke for stykke.
Testscenarie
Vores scenarie er enkelt, nemlig at bruge JavaScript til at få tidsintervallet for en IIS-log
Eksempler på IIS-logfiler:
#Software: Microsoft Internet Information Services 10.0 #Version: 1,0 #Date: 2016-08-18 06:53:55 #Fields: dato tid s-ip cs-metode cs-uri-stem cs-uri-query s-port cs-brugernavn c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-took 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 Vores mål er at få tidsrammen for den log:
Starttidspunkt: 2016-08-18 06:53:55 Sluttid: 2016-08-18 08:46:44
Brug readAsText()-implementeringen
At bruge readAsText() er relativt enkelt: Efter at have hentet strengen for hele filen, henter du de første 19 tegn i hver linje fra starten, afgør om datoformatet er opfyldt, hvis det er opfyldt, så er disse 19 tegn starttidspunktet, og det samme går gennem hver linje fra halen for at få sluttidspunktet, koden er som følger:
De løbende resultater af stikprøve-IIS-loggen (størrelse: 1k) er som forventet.
Men når vi først vælgerEn større IIS-log (størrelse: 2G) og browseren crasher。 Årsagen er, at readAsText() indlæser hele filen i hukommelsen først, så hvis filen er for stor, vil der ikke være nok hukommelse, og browserprocessen vil crashe.
Brug readAsArArBuffer()-implementeringen
Da File-objektet i JavaScript arver fra Blob, kan vi bruge Blob.slice()-metoden til at skære filen i små stykker, og den generelle idé er:
Først tager du de første 10.000 indhold i filen og konverterer det til tekst Tag de første 19 tegn i hver linje fra begyndelsen for at afgøre, om datoformatet er opfyldt, og hvis ja, er disse 19 tegn starttidspunktet Tag derefter de 10.000 ord i slutningen af filen og konverter det til tekst På samme måde skal du gennemgå hver linje fra haleindholdet for at få sluttidspunktet
Koden er som følger:
Ved at bruge readAsArrayBuffer() kunne vi opnå de ønskede resultater på meget kort tid, selv med mere end 2G IIS-logs.
|