过去Web程序不能替代桌面程序的一个重要原因就在于浏览器对于文件操作API的缺失。照片处理中的裁剪、滤镜,二维码的读取与识别,文档的查看和编辑等,这些操作无一不依赖文件的操作,HTML5赋予了浏览器几乎和本地程序同等强大的文件操作能力。
File API是HTML5在DOM标准中添加的功能,它允许Web内容在用户授权的情况下选择本地文件并读取内容一通过 File,FileList 和FileReader等对象共同作用来实现。
由于Web环境的特殊性,为了考虑文件安全问题,浏览器不允许JavaScript直接访问文件系统,但可以通过file类型的input元素或者拖放的方式选择文件操作。
File表单可以让用户选取一个或者多个文件(multiple 属性),通过FileAPI,可在用户选择文件后访问到代表了所选文件列表的FileList对象,FileList 对象是一个类数组的对象,其中包含着一个或多个File对象。如果没有multiple属性或者用户只选了一个文件,那么只需要访问FileList对象的第一个元素:
使用input元素时,用户在选择文件后会触发其change事件:
和其他类数组对象一样,FileList 也有length属性,可以轻松遍历其File对象:
File对象有3个很有用的属性,包括了关于该文件的许多有用信息。
(1) name: 文件名,不包含路径信息。
(2) size: 文件大小,以B为单位。
(3) type:文件的MIME type。
需要注意的是,这3个属性都是只读的。
使用拖曳的方式来选择文件的效果,需要通过访问dataTransfer的files属性来实现。
下面通过一个案例来演示具体效果,如示例所示。
【示例】 使用拖曳的方式选择文件
用Chrome浏览器访问示例。
前面讲到表单或者dataTansier对象中的File类型的实例代表着这个文件,但是这个文件对象只能访问到一些基本的信息(大小和文件名等),如果要访问文件的具体内容,还得借助FileReader对象。
FileReader对象可以将文件对象转换为字符串、DataURL对象或者二进制字符串等,以进行进一步操作。例如,在做图片上传功能时,可以先对选择的图片进行预览或者剪裁,待用户确认无误后再进行上传,可以节省许多不必要的带宽。以前文的拖曳文件例子为基础,加上拖曳图片预览功能,代码如示例所示。
【示例】 FileReader对象
用浏览器访问该页面。
从上面的例子可以看到FileReader()的基本用法。readAsDataURL()方法用于读取文件,它接收一个File 或者Blob对象的实例作为参数,并将文件内容转换为一个base64编码的URL字符串,并通过load事件将结果传递到e.target.result上。FileReader对象除了readAsDataURL()方法外,还有其他几个方法用于读取文件内容的操作。
(1) readAsArrayBuffer(Blob|File): 读取文件,最后result属性将包含ArrayBuffer对象以表示文件内容。ArrayBuffer 对象用来表示固定长度二进制数据的缓冲区。
(2) readAsBinaryString(Blob|File):读取文件, result属性包含文件的原始二进制数据。每个字节均由一个[0.255]范围内的整数表示。
(3) readAsText(BloblFile,encoding): 以文本方式读入文件,并可以指定返回数据的编码,默认为UTF-8。
(4) abort): 终止正在进行的读取操作。如果FileReader 对象没有进行读取操作,调用此方法会抛出DOM_FILE_ABORT_ERR异常。
以上读取文件操作的方法有两个共同点,一是都接受一个 Blob或File类型的对象。
Blob对象还支持slice() 方法,用于对数据进行切割:
File对象同样继承了Blob的slice()方法,可以利用此方法对File对象预先进行分割,然后再读取、上传,最后在服务器端进行组装——异步上传的原理就是这样。如果再记住分割点,这样即使网络中途断掉,也可以在下次传输时从断点续传。
除了都接受Blob和File对象,这些方法另外一个共同点是,由于JavaScript本身基于事件驱动,这些和平台相关的方法都是异步方法。即调用时立即返回,读取文件操作完成后再触发相应的load事件。
除了load事件,FileReader 对象还会调用这样一些事件处理程序。
(1) onabort:当读取操作被终止时调用(调用abort 方法)
(2) onerror: 当读取操作发送错误时调用。
(3) onload: 当读取操作成功完成时调用。
(4) onloadend:当读取操作完成时调用,不管是成功还是失败,该处理程序在onload或者onerror后调用。
(5) onloadstart: 当读取操作将要开始之前调用。
(6) onprogress:在读取数据过程中周期性调用。该事件为最有用的事件,在加载较大的文件时,可以提供一个进度条让用户知道当前加载进度,不让用户产生焦躁感。
e.total存储着当前文件的总大小(字节),e.loaded 表示当前文件已经加载了多少。
要想将图片文件转换成可以直接在HTML里引用的URL,除了前文提到的readAsDataURL()方法,还可以使用window.URL .createObjectURL()方法:
objectURL最后会得到一个类似blob: null/a672ae4c- f84e- 45d2- -87ae-f45dc986d601的字符串,这个字符串可以直接被IMG等元素引用。
objectURL和dataURL一样可以直接被img的src属性引用,就像Windows平台下的文件句柄或者Linux下的文件描述符,在使用完之后通常还要调用window.URL.revokeObjectURL()方法进行释放,如果不显示调用该方法,objectURL 将会在文档卸载时自动释放。对于前文的例子可以简单修改为URL对象版本:
有了操作文件的利器,读者可以做一些有趣的功能,比如实现类似Photoshop中图片处理的滤镜或者读取PDF文档并转换为HTML格式等。
如果您觉得本文的内容对您的学习有所帮助:
关键字:
jquery