La API FileReader de HTML5 permite al navegador cliente leer los archivos locales del usuario, de modo que el archivo subido ya no sea leído por el servidor, lo que reduce considerablemente la carga para el servidor y ahorra el tiempo necesario para subir el archivo. Sin embargo, en la práctica, descubrí que puedo manejar fácilmente un archivo de registro de 300k con FileReader.readAsText(), pero cuando el archivo de registro es tan grande como 1G o incluso 2G, el navegador se bloquea. Esto se debe a que readAsText() carga el archivo destino en la memoria de una vez, haciendo que la memoria supere el límite. Así que si la aplicación web a menudo necesita procesar archivos grandes, deberíamos usar FileReader.readAsArrayBuffer() para leer los archivos pieza a pieza.
Escenario de prueba
Nuestro escenario es sencillo, que consiste en usar JavaScript para obtener el rango de tiempo de un registro IIS
Ejemplo de registros IIS:
#Software: Microsoft Internet Information Services 10.0 #Version: 1.0 #Date: 2016-08-18 06:53:55 #Fields: fecha hora s-ip cs-método 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; +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)+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; +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 Nuestro objetivo es obtener el marco temporal de ese registro:
Hora de inicio: 2016-08-18 06:53:55 Hora final: 2016-08-18 08:46:44
Utiliza la implementación de readAsText()
Usar readAsText() es relativamente sencillo: tras obtener la cadena de todo el archivo, obtener los primeros 19 caracteres de cada línea desde el principio, determinar si se cumple el formato de fecha; si se cumple, entonces estos 19 caracteres son la hora de inicio, y lo mismo se aplica a cada línea desde la cola para obtener la hora final, el código es el siguiente:
Los resultados en ejecución del registro de muestra IIS (tamaño: 1k) son los que esperábamos.
Pero una vez que elegimosUn registro IIS más grande (tamaño: 2G) y el navegador se bloquea。 La razón es que readAsText() cargará primero todo el archivo en memoria, así que si el archivo es demasiado grande, no habrá suficiente memoria y el proceso del navegador se bloqueará.
Utiliza la implementación readAsArrayBuffer()
Dado que el objeto archivo en JavaScript hereda de Blob, podemos usar el método Blob.slice() para cortar el archivo en pequeños trozos, la idea general es:
Primero, toma los primeros 10k contenidos del archivo y conviértelos a texto Toma los primeros 19 caracteres de cada línea desde el principio para determinar si se cumple el formato de fecha, y si es así, estos 19 caracteres son la hora de inicio Luego toma el contenido de 10k al final del archivo y conviértelo en texto De manera similar, recorre cada línea desde el contenido de la cola para obtener la hora final
El código es el siguiente:
Usando readAsArrayBuffer(), pudimos obtener los resultados que queríamos en muy poco tiempo, incluso con más de 2G de logs IIS.
|