HTML5 File API 全介绍

  在 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 又有哪些属性呢?异步

  • name:文件名,该属性只读。
  • size:文件大小,单位为字节,该属性只读。
  • type:文件的 MIME 类型,若是分辨不出类型,则为空字符串,该属性只读。
  • lastModified:文件的上次修改时间,格式为时间戳。
  • lastModifiedDate:文件的上次修改时间,格式为 Date 对象实例。

  咱们能够选一个文件,本身打印出来看看。函数

三、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 对象有两个只读属性:

  • size:二进制数据的大小,单位为字节。(文件上传时能够在前端判断文件大小是否合适)
  • type:二进制数据的 MIME 类型,所有为小写,若是类型未知,则该值为空字符串。(文件上传时能够在前端判断文件类型是否合适)

四、FileReader

  FileReader API 才是咱们接下去完成一些任务的关键。FileReader API 用于读取文件,即把文件内容读入内存。它的参数是 File 对象或 Blob 对象

  对于不一样类型的文件,FileReader 提供不一样的方法读取文件。

  • readAsText(Blob|File, opt_encoding):返回文本字符串。默认状况下,文本编码格式是 UTF-8,能够经过可选的格式参数,指定其余编码格式的文本。
  • readAsDataURL(Blob|File):返回一个基于 Base64 编码的 data-uri 对象。
  • readAsArrayBuffer(Blob|File):返回一个 ArrayBuffer 对象。

  除了以上三种不一样的读取文件方法,FileReader API 还有一个 abort 方法,用于停止文件上传。

var reader = new FileReader(); reader.abort();

  FileReader 对象采用异步方式读取文件,能够为一系列事件指定回调函数。

  • onabort 方法:读取中断或调用 reader.abort() 方法时触发。
  • onerror 方法:读取出错时触发。
  • onload 方法:读取成功后触发。
  • onloadend 方法:读取完成后触发,不论是否成功。触发顺序排在 onload 或 onerror 后面。
  • onloadstart 方法:读取将要开始时触发。
  • onprogress 方法:读取过程当中周期性触发。(能够用来获取文件读取的进度)

  获取到了文件的 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)。

  利用它们之间的转换能够作些什么好玩的事呢?好比能够上传图片,对图片作各类处理,而后保存等。

相关文章
相关标签/搜索