L'API FileReader di HTML5 permette al browser client di leggere i file locali dell'utente, così che il file caricato non venga più letto dal server, riducendo notevolmente il carico sul server e risparmiando il tempo necessario per caricare il file. Tuttavia, in pratica, ho scoperto di poter gestire facilmente un file di log da 300k con FileReader.readAsText(), ma quando il file di log è grande come 1G o anche 2G, il browser si blocca. Questo perché readAsText() caricherà il file di destinazione in memoria tutto in una volta, facendo superare il limite della memoria. Quindi, se l'applicazione web deve spesso elaborare file grandi, dovremmo usare FileReader.readAsArrayBuffer() per leggere i file pezzo per pezzo.
Scenario di prova
Il nostro scenario è semplice, ovvero usare JavaScript per ottenere l'intervallo temporale di un log IIS
Esempi di log IIS:
#Software: Microsoft Internet Information Services 10.0 #Version: 1.0 #Date: 18-08-2016 06:53:55 #Fields: data ora s-ip cs-method cs-uri-stem cs-uri-query s-porta 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; +Tridente/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; +Tridente/7.0; +rv:11.0)+tipo+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; +Tridente/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; +Tridente/7.0; +rv:11.0)+like+Gecko - 200 0 0 6 Il nostro obiettivo è ottenere il periodo temporale di quel registro:
Ora di inizio: 2016-08-18 06:53:55 Ora di fine: 2016-08-18 08:46:44
Usa l'implementazione readAsText()
Usare readAsText() è relativamente semplice: dopo aver ottenuto la stringa dell'intero file, si ottengono i primi 19 caratteri di ogni riga dall'inizio, si determina se il formato della data è soddisfatto; se è soddisfatto, questi 19 caratteri sono l'ora di inizio, e lo stesso viene fatto in ogni riga dalla coda per ottenere l'ora di fine, il codice è il seguente:
I risultati in esecuzione del campione di log IIS (dimensione: 1k) sono come ci aspettavamo.
Ma una volta che scegliamoUn log IIS più grande (dimensione: 2G) e il browser va in crash。 Il motivo è che readAsText() caricherà prima l'intero file in memoria, quindi se il file è troppo grande, non ci sarà abbastanza memoria e il processo del browser si bloccherà.
Usa l'implementazione readAsArrayBuffer()
Poiché l'oggetto File in JavaScript eredita da Blob, possiamo usare il metodo Blob.slice() per tagliare il file in piccoli pezzi, l'idea generale è:
Per prima cosa, prendi i primi 10k contenuti del file e convertili in testo Prendi i primi 19 caratteri di ogni riga dall'inizio per determinare se il formato della data è stato rispettato e, in tal caso, questi 19 caratteri indicano l'orario di inizio Poi prendi il contenuto da 10k alla fine del file e convertilo in testo Allo stesso modo, attraversa ogni linea dal contenuto della coda per ottenere l'orario finale
Il codice è il seguente:
Usando readAsArrayBuffer(), siamo riusciti a ottenere i risultati desiderati in pochissimo tempo, anche con più di 2G IIS log.
|