当前位置: 首页 > news >正文

HTML5 File API 全介绍

  在 HTML5 File API 出现之前,前端对于文件的操作是非常有局限性的,大多需要配合后端实现。出于安全角度考虑,从本地上传文件时,代码不可能获取文件在用户本地的地址,所以纯前端不可能完成一些类似图片预览的功能。但是 File API 的出现,让这一切变成了可能。

1、FileList 对象

  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,而这通常发生在表单选择文件或者拖拽文件中。

2、File对象

  一个 FileList 对象包含了我们选中的 File 对象,那么一个 File 又有哪些属性呢?

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

  我们可以选一个文件,自己打印出来看看。

3、Blob

  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 类型,全部为小写,如果类型未知,则该值为空字符串。(文件上传时可以在前端判断文件类型是否合适)

4、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 编码,做一些诸如图片预览的功能,也就手到擒来了,有兴趣的可以自己尝试下,类似的还有文字预览啊,等等。

5、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>

6、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)。

  利用它们之间的转换可以做些什么好玩的事呢?比如可以上传图片,对图片做各种处理,然后保存等。

转载于:https://www.cnblogs.com/goloving/p/10415670.html

相关文章:

  • Grafana 利用Grafana Variables变量配置快速切换不同主机的图表数据展示
  • 在Windos上安装Nginx
  • [UE4]VR手柄按键参考
  • 2019 GDUT Rating Contest II : Problem G. Snow Boots
  • ORACLE查看数据库已安装补丁
  • VueJs之自动打开浏览器配置
  • ssh远程 和 上传/下载工具
  • DQN(Deep Reiforcement Learning) 发展历程(二)
  • Python使用Flask框架,结合Highchart,自定义导出菜单项目及顺序
  • 软件的安装
  • day8 编码2
  • HNOI/AHOI2018题解
  • CodeSmith 一、连接Mysql
  • 微信小微商户直连接口详解
  • js----第二篇
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • 《剑指offer》分解让复杂问题更简单
  • 【面试系列】之二:关于js原型
  • canvas绘制圆角头像
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • javascript从右向左截取指定位数字符的3种方法
  • Koa2 之文件上传下载
  • LintCode 31. partitionArray 数组划分
  • Python 基础起步 (十) 什么叫函数?
  • Python十分钟制作属于你自己的个性logo
  • Spring声明式事务管理之一:五大属性分析
  • ViewService——一种保证客户端与服务端同步的方法
  • vue--为什么data属性必须是一个函数
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 机器学习 vs. 深度学习
  • 理清楚Vue的结构
  • 面试总结JavaScript篇
  • 深入 Nginx 之配置篇
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 系统认识JavaScript正则表达式
  • 学习笔记TF060:图像语音结合,看图说话
  • 学习使用ExpressJS 4.0中的新Router
  • 异步
  • 译有关态射的一切
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #{} 和 ${}区别
  • #Spring-boot高级
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (+4)2.2UML建模图
  • (1)(1.11) SiK Radio v2(一)
  • (1)(1.9) MSP (version 4.2)
  • (12)目标检测_SSD基于pytorch搭建代码
  • (C#)一个最简单的链表类
  • (Java)【深基9.例1】选举学生会
  • (js)循环条件满足时终止循环
  • (zhuan) 一些RL的文献(及笔记)
  • (二十三)Flask之高频面试点
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011