在 HTML5 File API 出现以前,前端对于文件的操做是很是有局限性的,大多须要配合后端实现。出于安全角度考虑,从本地上传文件时,代码不可能获取文件在用户本地的地址,因此纯前端不可能完成一些相似图片预览的功能。可是 File API 的出现,让这一切变成了可能。前端
一、FileList 对象canvas
FileList 对象针对表单的 file 控件。当用户经过 file 控件选取文件后,这个控件的 files 属性值就是 FileList 对象。它在结构上相似于数组,包含用户选取的多个文件。若是 file 控件没有设置 multiple 属性,那么用户只能选择一个文件,FileList 对象也就只有一个元素了。后端
好比我选择了两个文件,控制台打印:数组
FileList {0: File, 1: File, length: 2} 0: File 1: File length:2 __proto__: Object
通常来讲,咱们不可能手动构造 FileList 对象,只能被动地读取,也就是说只有用户主动触发了文件读取行为,js 才能访问到 FileList,而这一般发生在表单选择文件或者拖拽文件中。缓存
二、File对象安全
一个 FileList 对象包含了咱们选中的 File 对象,那么一个 File 又有哪些属性呢?异步
咱们能够选一个文件,本身打印出来看看。函数
三、Blobthis
File 对象是继承自 Blob 对象的,Blob 又是什么鬼?编码
Blob(Binary Large Object)对象表明了一段二进制数据,提供了一系列操做接口。其余操做二进制数据的 API(好比 File 对象),都是创建在 Blob 对象基础上的,继承了它的属性和方法。
生成 Blob 对象有两种方法:一种是使用 Blob 构造函数,另外一种是对现有的 Blob 对象使用 slice 方法切出一部分。
(1)Blob 构造函数,接受两个参数。第一个参数是一个包含实际数据的数组,第二个参数是数据的类型,这两个参数都不是必需的。
(2)Blob 对象的 slice 方法,将二进制数据按照字节分块,返回一个新的 Blob 对象。
var a = ["hello", "world"]; var myBlob = new Blob(a, { "type" : "text/xml" }); var newBlob = myBlob.slice(0, 5); console.log(newBlob);
Blob 对象有两个只读属性:
四、FileReader
FileReader API 才是咱们接下去完成一些任务的关键。FileReader API 用于读取文件,即把文件内容读入内存。它的参数是 File 对象或 Blob 对象。
对于不一样类型的文件,FileReader 提供不一样的方法读取文件。
除了以上三种不一样的读取文件方法,FileReader API 还有一个 abort 方法,用于停止文件上传。
var reader = new FileReader(); reader.abort();
FileReader 对象采用异步方式读取文件,能够为一系列事件指定回调函数。
获取到了文件的 base64 编码,作一些诸如图片预览的功能,也就手到擒来了,有兴趣的能够本身尝试下,相似的还有文字预览啊,等等。
五、URL
还有个强大的东西——URL 对象!
调用 URL 对象的 createObjectURL 方法,传入一个 File 对象或者 Blob 对象,能生成一个连接。
var objecturl = window.URL.createObjectURL(blob);
上面的代码会对二进制数据生成一个 URL,这个 URL 能够放置于任何一般能够放置 URL 的地方,好比 img 标签的 src 属性。须要注意的是,即便是一样的二进制数据,每调用一次 URL.createObjectURL 方法,就会获得一个不同的 URL。这个 URL 的存在时间,等同于网页的存在时间,一旦网页刷新或卸载,这个 URL 就失效。(File 和 Blob 又未尝不是这样呢)除此以外,也能够手动调用 URL.revokeObjectURL 方法,使 URL 失效。
对于 File 或者 Blob 对象,咱们能够这样理解,它们的存在,依赖于页面,而 URL 能给这些 "转瞬即逝" 的二进制对象一个临时的指向地址。这个临时的地址还有什么用呢?也能作图片预览,相比前面用 readAsDataURL 的实现,更简单了。
<input type='file' multiple /><br/>
<img />
<script> document.querySelector("input").onchange = function() { var files = this.files; document.querySelector("img").src = window.URL.createObjectURL(files[0]); } </script>
六、Canvas & dataURL & Blob
canvas 中有 toDataURL 函数,能够将 canvas 转为 dataURL 形式的 base64 编码,而 Blob 也能够转为 dataURL,这三者之间是否能够互相转换?有没有什么实用之处?
(1)canvas -> dataURL
用 toDataURL 方法,比较简单,很少说。
(2)blob -> dataURL
用 FileReader 的 readAsDataURL 方法
(3)dataURL -> blob
这个函数有点屌
function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], {type:mime}); }
(4)dataURL - canvas
将 image 的 src 属性置为 dataURL,再用 drawImage 方法画上去。
(5)blob - canvas
如何把二进制形式的图片画上 canvas?先用 readAsDataURL 转为 dataURL,接着就是 (4) 的事情了。
(6)canvas - blob
canvas 有原生的 toBlob 方法,使得图片文件能够被缓存或保存到本地
canvas 转为 blob 也能够用 dataURL 作跳板,先将 canvas 转为 dataURL(1),再用 dataURL 转为 blob(3)。
利用它们之间的转换能够作些什么好玩的事呢?好比能够上传图片,对图片作各类处理,而后保存等。