HTML5:s FileReader API tillåter klientwebbläsaren att läsa användarens lokala filer, så att den uppladdade filen inte längre läses av servern, vilket kraftigt minskar belastningen på servern och sparar tid som krävs för att ladda upp filen. Men i praktiken har jag upptäckt att jag enkelt kan hantera en 300k-loggfil med FileReader.readAsText(), men när loggfilen är så stor som 1G eller till och med 2G kraschar webbläsaren. Detta beror på att readAsText() laddar målfilen i minnet på en gång, vilket gör att minnet överskrider gränsen. Så om webbapplikationen ofta behöver bearbeta stora filer bör vi använda FileReader.readAsArrayBuffer() för att läsa filerna bit för bit.
Testscenario
Vårt scenario är enkelt, nämligen att använda JavaScript för att få tidsintervallet för en IIS-logg
Exempel på IIS-loggar:
#Software: Microsoft Internet Information Services 10.0 #Version: 1.0 #Date: 2016-08-18 06:53:55 #Fields: datum, tid s-ip cs-metod 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)+lika+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)+lika+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)+lika+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)+lika+Gecko - 200 0 0 6 Vårt mål är att få tidsramen för den loggen:
Starttid: 2016-08-18 06:53:55 Sluttid: 2016-08-18 08:46:44
Använd readAsText()-implementeringen
Att använda readAsText() är relativt enkelt, efter att ha hämtat strängen för hela filen, hämta de första 19 tecknen i varje rad från början, avgör om datumformatet uppfylls, om det är uppfyllt, då är dessa 19 tecken starttiden, och samma går genom varje rad från slutet för att få sluttiden, koden är följande:
De löpande resultaten i urvalsloggen (storlek: 1k) är som vi förväntade oss.
Men när vi väl väljerEn större IIS-logg (storlek: 2G) och webbläsaren kraschar。 Anledningen är att readAsText() först laddar hela filen i minnet, så om filen är för stor finns det inte tillräckligt med minne och webbläsarprocessen kraschar.
Använd readAsArArBuffer()-implementation
Eftersom File-objektet i JavaScript ärver från Blob kan vi använda Blob.slice()-metoden för att dela filen i små bitar, den allmänna idén är:
Först, ta de första 10 000 innehållet i filen och konvertera det till text Ta de första 19 tecknen i varje rad från början för att avgöra om datumformatet uppfylls, och i så fall är dessa 19 tecken starttiden Sedan tar du det 10 000 000 innehållet i slutet av filen och konverterar det till text På samma sätt, traversera varje linje från svansens innehåll för att få sluttiden
Koden är följande:
Med hjälp av readAsArrayBuffer() kunde vi få de resultat vi ville ha på mycket kort tid, även med mer än 2G IIS-loggar.
|