【前端知乎系列】ArrayBuffer 和 Blob 对象


本文首发在 我的博客 javascript

更多丰富的前端学习资料,能够查看个人 Github: Leo-JavaScript ,内容涵盖 数据结构与算法、HTTPHybrid面试题ReactAngularTypeScriptWebpack等等。

点个 Star 不迷路~html

ArrayBuffer 对象与 Blob 对象你们或许不太陌生,常见于文件上传操做处理(如处理图片上传预览等问题)。前端

那么本文将与你们深刻介绍二者。java

1、ArrayBuffer 对象

ArrayBuffer 对象是 ES6 才归入正式 ECMAScript 规范,是 JavaScript 操做二进制数据的一个接口。ArrayBuffer 对象是以数组的语法处理二进制数据,也称二进制数组。git

介绍 ArrayBuffer 对象还需介绍 TypedArray 视图和 DataView 视图,本文不具体介绍,详细能够查看阮一峰老师《ECMAScript 6 入门 ArrayBuffer》 章节。es6

1. 概念介绍

ArrayBuffer 对象表明储存二进制数据的一段内存,它不能直接读写,只能经过视图(TypedArray视图和DataView视图)来读写,视图的做用是以指定格式解读二进制数据。github

关于 TypedArray 视图和 DataView 视图 ,能够查看阮一峰老师《ECMAScript 6 入门 ArrayBuffer》 章节的介绍。面试

2. 对象使用

浏览器原生提供 ArrayBuffer() 构造函数,用来生成实例。算法

参数:json

  • 整数,表示二进制数据占用的字节长度。

返回值:

  • 一个指定大小的 ArrayBuffer 对象,其内容被初始化为 0。
const buffer = new ArrayBuffer(32);复制代码

上面代码表示实例对象 buffer 占用 32 个字节。

3. 实例属性和方法

ArrayBuffer 对象有实例属性 byteLength ,表示当前实例占用的内存字节长度(单位字节),一单建立就不可变动(只读)

const buffer = new ArrayBuffer(32);buffer.byteLength; // 32复制代码

ArrayBuffer 对象有实例方法 slice(),用来复制一部份内存。

参数以下:

  • start,整数类型,表示开始复制的位置。默认从 0 开始。

  • end,整数类型,表示结束复制的位置(不包括结束的位置)。若是省略,则表示复制到结束。

const buffer = new ArrayBuffer(32);const buffer2 = buffer.slice(0);复制代码

4. 兼容性


图片来自 MDN

2、Blob 对象

1. 概念介绍

Blob 全称:Binary Large Object (二进制大型对象)。

Blob 对象表示一个二进制文件的数据内容,一般用来读写文件,好比一个图片文件的内容就能够经过 Blob 对象读写。

ArrayBuffer 区别:

  • Blob 用于操做 二进制文件
  • ArrayBuffer 用于操做 内存

2. 对象使用

浏览器原生提供 Blob() 构造函数,用来生成实例。

Blob 的内容由参数数组中给出的值的串联组成。

const leoBlob = new Blob(array [, options]);复制代码

参数:

  • array,必填,成员是字符串或二进制对象,表示新生成的Blob实例对象的内容;

成员能够是一个由 ArrayBuffer ,  ArrayBufferView , Blob ,  DOMString 等对象构成的 Array ,或者其余相似对象的混合体,它将会被放进 BlobDOMStrings会被编码为UTF-8

  • options,可选,是一个配置对象,这里介绍经常使用的属性 type,表示数据的 MIME 类型,默认空字符串;

options 目前可能有两个属性:typeendings

endings 用于指定包含行结束符 \n 的字符串如何被写入,默认值 transparent。它只有这两个值:native (表明行结束符会被更改成适合宿主操做系统文件系统的换行符)和 transparent (表明会保持blob中保存的结束符不变)。

使用案例:

const leoHtmlFragment = ['<a id="a"><b id="b">hey leo!</b></a>']; // 一个包含 DOMString 的数组const leoBlob = new Blob(leoHtmlFragment, {type : 'text/html'});   // 获得 blob复制代码

该代码中,实例对象 leoBlob 包含的是字符串。生成实例时,指定数据类型为 text/html

还可使用 Blob 保存 JSON 数据:

const obj = { hello: 'leo' };const blob = new Blob([ JSON.stringify(obj) ], {type : 'application/json'});复制代码

3. 实例属性和方法

Blob 具备两个实例属性:

  • size:文件的大小,单位为字节。

  • type:文件的 MIME 类型。若是类型没法肯定,则返回空字符串。

const leoHtmlFragment = ['<a id="a"><b id="b">hey leo!</b></a>']; // 一个包含 DOMString 的数组const leoBlob = new Blob(leoHtmlFragment, {type : 'text/html'});   // 获得 blobleoBlob.size; // 38leoBlob.type; // "text/html"复制代码

Blob 实例方法:

  • clice:方法用于建立一个包含源 Blob 的指定字节范围内的数据的新 Blob 对象。
const newBlob = oldBlob.slice([start [, end [, contentType]]])复制代码

包含三个参数:

start,可选,起始的字节位置,默认 0;

end,可选,结束的字节位置,默认 size 属性的值,不包含该位置;

contentType,可选,新实例的数据类型(默认为空字符串);

4. 兼容性


图片来自 MDN

5. 实际案例

5.1 获取文件信息

文件选择器 <input type="file"> 用来让用户选取文件。出于安全考虑,浏览器不容许脚本自行设置这个控件的 value 属性,即文件必须是用户手动选取的,不能是脚本指定的。一旦用户选好了文件,脚本就能够读取这个文件。

文件选择器返回一个 FileList 对象,该对象是个类数组对象,每一个成员都是一个 File 实例对象。File 实例对象是一个特殊的 Blob 实例,增长了 namelastModifiedDate 属性。

也包括拖放 APIdataTransfer.files 返回的也是一个 FileList 对象,成员也是 File 实例对象。

// HTML 代码以下// <input type="file" accept="image/*" multiple onchange="fileinfo(this.files)"/>function fileinfo(files) {  for (let i = 0; i < files.length; i++) {    let f = files[i];    console.log(      f.name, // 文件名,不含路径      f.size, // 文件大小,Blob 实例属性      f.type, // 文件类型,Blob 实例属性      f.lastModifiedDate // 文件的最后修改时间    );  }}复制代码

5.2 下载文件

在 AJAX 请求中,指定 responseType 属性为 blob ,皆能够下下载一个 Blob 对象。

function getBlob(url, callback) {  const xhr = new XMLHttpRequest();  xhr.open('GET', url);  xhr.responseType = 'blob';  xhr.onload = function () {    callback(xhr.response);  }  xhr.send(null);}复制代码

而后,xhr.response 拿到的就是一个 Blob 对象。

5.3 生成 URL

浏览器容许使用 URL.createObjectURL() 方法,针对 Blob 对象生成一个临时URL,以便于某些 API 使用。

如做为图片预览的 URL。

这个 URL 以 blob:// 开头,代表对应一个 Blob 对象,协议头后面是一个识别符,用来惟一对应内存里面的 Blob 对象。这一点与 data://URL(URL 包含实际数据)和 file://URL(本地文件系统里面的文件)都不同。

const droptarget = document.getElementById('droptarget');droptarget.ondrop = function (e) {  const files = e.dataTransfer.files;  for (let i = 0; i < files.length; i++) {    let type = files[i].type;    if (type.substring(0,6) !== 'image/')      continue;    let img = document.createElement('img');    img.src = URL.createObjectURL(files[i]);    img.onload = function () {      this.width = 100;      document.body.appendChild(this);      URL.revokeObjectURL(this.src);    }  }}复制代码

代码中,经过为拖放的图片文件生成一个 URL,做为预览的缩略图。

浏览器处理 Blob URL 就跟普通的 URL 同样,若是 Blob 对象不存在,返回404状态码;若是跨域请求,返回403状态码。Blob URL 只对 GET 请求有效,若是请求成功,返回200状态码。因为 Blob URL 就是普通 URL,所以能够下载。

5.4 读取文件

取得 Blob 对象之后,能够经过 FileReader 对象,读取 Blob 对象的内容,即文件内容。

FileReader 对象提供四个方法。将 Blob 对象做为参数传入,而后以指定的格式返回。

  • FileReader.readAsText():返回文本,须要指定文本编码,默认为 UTF-8。
  • FileReader.readAsArrayBuffer():返回 ArrayBuffer 对象。
  • FileReader.readAsDataURL():返回 Data URL。
  • FileReader.readAsBinaryString():返回原始的二进制字符串。

下面是 FileReader.readAsText() 方法的例子,用来读取文本文件:

// HTML 代码以下// <input type='file' onchange='readfile(this.files[0])'></input>// <pre id='output'></pre>function readfile(f) {  let reader = new FileReader();  reader.readAsText(f);  reader.onload = function () {    let text = reader.result;    let out = document.getElementById('output');    out.innerHTML = '';    out.appendChild(document.createTextNode(text));  }  reader.onerror = function(e) {    console.log('Error', e);  };}复制代码

下面是 FileReader.readAsArrayBuffer() 方法的例子,用于读取二进制文件:

// HTML 代码以下// <input type="file" onchange="typefile(this.files[0])"></input>function typefile(file) {  // 文件开头的四个字节,生成一个 Blob 对象  let slice = file.slice(0, 4);  let reader = new FileReader();  // 读取这四个字节  reader.readAsArrayBuffer(slice);  reader.onload = function (e) {    let buffer = reader.result;    // 将这四个字节的内容,视做一个32位整数    let view = new DataView(buffer);    let magic = view.getUint32(0, false);    // 根据文件的前四个字节,判断它的类型    switch(magic) {      case 0x89504E47: file.verified_type = 'image/png'; break;      case 0x47494638: file.verified_type = 'image/gif'; break;      case 0x25504446: file.verified_type = 'application/pdf'; break;      case 0x504b0304: file.verified_type = 'application/zip'; break;    }    console.log(file.name, file.verified_type);  };}复制代码

3、参考资料

1. 《ArrayBuffer 对象,Blob 对象》

https://wangdoc.com/javascript/bom/arraybuffer.html

2. 《ECMAScript 6 入门 ArrayBuffer》

https://es6.ruanyifeng.com/#docs/arraybuffe


bg
相关文章
相关标签/搜索