L’API FileReader de HTML5 permet au navigateur client de lire les fichiers locaux de l’utilisateur, de sorte que le fichier téléchargé n’est plus lu par le serveur, ce qui réduit considérablement la charge sur le serveur et fait gagner le temps nécessaire pour télécharger le fichier. Cependant, en pratique, j’ai constaté que je peux facilement gérer un fichier journal de 300k avec FileReader.readAsText(), mais lorsque le fichier journal est aussi grand que 1G voire 2G, le navigateur plante. Cela s’explique par le fait que readAsText() charge le fichier cible en mémoire d’un seul coup, ce qui fait dépasser la limite de la mémoire. Donc, si l’application web doit souvent traiter de gros fichiers, nous devrions utiliser FileReader.readAsArrayBuffer() pour lire les fichiers morceau par morceau.
Scénario test
Notre scénario est simple : utiliser JavaScript pour obtenir la plage de temps d’un journal IIS
Exemples de journaux IIS :
#Software : Microsoft Internet Information Services 10.0 #Version : 1.0 #Date : 18-08-2016 06:53:55 #Fields : date time s-ip cs-méthode cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Référent) sc-status sc-sous-état 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 Notre objectif est d’obtenir la période de ce journal :
Heure de début : 18-08-2016 06:53:55 Heure de fin : 18-08-2016 08:46:44
Utiliser l’implémentation readAsText()
Utiliser readAsText() est relativement simple : après avoir obtenu la chaîne complète du fichier, obtenir les 19 premiers caractères de chaque ligne depuis le début, déterminer si le format de date est respecté, si il est satisfait, alors ces 19 caractères sont l’heure de début, et il en va de même pour chaque ligne depuis la queue pour obtenir l’heure de fin, le code est le suivant :
Les résultats de l’échantillon de journal IIS (taille : 1k) sont comme prévu.
Mais une fois que nous avons choisiUn journal IIS plus grand (taille : 2G) et le navigateur plante。 La raison est que readAsText() chargera d’abord tout le fichier en mémoire, donc si le fichier est trop volumineux, il n’y aura pas assez de mémoire et le processus du navigateur plantera.
Utiliser l’implémentation readAsArrayBuffer()
Puisque l’objet fichier en JavaScript hérite de Blob, nous pouvons utiliser la méthode Blob.slice() pour découper le fichier en petits morceaux, l’idée générale est la suivante :
Premièrement, prenez les 10 000 premiers contenus du fichier et convertissez-les en texte Prenez les 19 premiers caractères de chaque ligne depuis le début pour déterminer si le format de date est respecté, et si oui, ces 19 caractères indiquent l’heure de début Ensuite, prenez le contenu de 10k à la fin du fichier et convertissez-le en texte De même, parcourez chaque ligne depuis le contenu de la queue pour obtenir l’heure de fin
Le code est le suivant :
Grâce à readAsArrayBuffer(), nous avons pu obtenir les résultats souhaités en très peu de temps, même avec plus de 2G de logs IIS.
|