架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 15487|回复: 3

[HTML/HTML5] 使用FileReader.readAsArrayBuffer()在浏览器中处理大文件

[复制链接]
发表于 2019-6-2 20:35:17 | 显示全部楼层 |阅读模式
HTML5的FileReader API可以让客户端浏览器对用户本地文件进行读取,这样就不再需要上传文件由服务器进行读取了,这大大减轻了服务器的负担,也节省了上传文件所需要的时间。不过在实践中我发现用FileReader.readAsText()可以轻易地处理一个300k的日志文件,但当日志文件有1G、甚至2G那么大,浏览器就会崩溃。这是因为readAsText()会一下子把目标文件加载至内存,导致内存超出上限。所以如果Web应用常常需要处理大文件时,我们应该使用FileReader.readAsArrayBuffer()来一块一块读取文件。

测试场景

我们的场景很简单,就是使用JavaScript来获取某个IIS日志的时间范围

样例IIS日志:

#Software: Microsoft Internet Information Services 10.0
#Version: 1.0
#Date: 2016-08-18 06:53:55
#Fields: date time s-ip cs-method 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)+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
我们的目标就是获取该段日志的时间范围:

开始时间:2016-08-18 06:53:55
结束时间:2016-08-18 08:46:44

使用readAsText()的实现

使用readAsText()实现是比较简单的,得到整个文件的字符串后,从头获取每一行的前19个字符,判断是否满足日期的格式,如果满足那么这19个字符就是开始时间,同理从尾部遍历每一行来获取结束时间,代码如下:


样例IIS日志(大小:1k)的运行结果符合我们的预期。

fa677ddb7ee404cc044e898dc879a386.gif

可是一旦我们选择了一个较大的IIS日志(大小:2G),浏览器就崩溃了。原因就是readAsText()会先把整个文件加载到内存中,那么如果文件太大,内存就不够用了,浏览器进程就会崩溃。
6b8dcd04d08bde08572f827156367ed7.gif

使用readAsArrayBuffer()的实现

由于JavaScript中的File对象继承自Blob,所以我们完全可以用Blob.slice()方法将文件切成小块来处理,大致思路是:

先取文件的前10k内容,转换成文本
从头获取每一行的前19个字符,判断是否满足日期的格式,如果满足那么这19个字符就是开始时间
再取文件尾部的10k内容,转换成文本
同理从尾部内容遍历每一行来获取结束时间

代码如下:


使用了readAsArrayBuffer()后,即使是2G多的IIS日志,我们也能在很短的时间内获得我们想要的结果。

4ce2cc4d9142603112ab81263636cb10.gif




上一篇:php调用短信验证码接口
下一篇:export命名导出与默认导出
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2019-6-2 20:39:24 | 显示全部楼层
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
发表于 2021-9-17 09:11:00 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
发表于 2021-12-21 18:26:43 | 显示全部楼层
学习和借鉴一下楼主的方法
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2024-4-20 16:14

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表