本文首发在个人【我的博客】
更多丰富的前端学习资料,能够查看个人 Github: 《Leo-JavaScript》,内容涵盖数据结构与算法、HTTP、Hybrid、面试题、React、Angular、TypeScript和Webpack等等。
点个 Star 不迷路~javascript
ArrayBuffer
对象与 Blob
对象你们或许不太陌生,常见于文件上传操做处理(如处理图片上传预览等问题)。html
那么本文将与你们深刻介绍二者。前端
ArrayBuffer
对象是 ES6 才归入正式 ECMAScript 规范,是 JavaScript 操做二进制数据的一个接口。ArrayBuffer
对象是以数组的语法处理二进制数据,也称二进制数组。java
介绍 ArrayBuffer
对象还需介绍 TypedArray
视图和 DataView
视图,本文不具体介绍,详细能够查看阮一峰老师《ECMAScript 6 入门 ArrayBuffer》 章节。git
ArrayBuffer
对象表明储存二进制数据的一段内存,它不能直接读写,只能经过视图(TypedArray
视图和DataView
视图)来读写,视图的做用是以指定格式解读二进制数据。es6
关于 TypedArray
视图和 DataView
视图 ,能够查看阮一峰老师《ECMAScript 6 入门 ArrayBuffer》 章节的介绍。github
浏览器原生提供 ArrayBuffer()
构造函数,用来生成实例。面试
参数:算法
返回值:json
ArrayBuffer
对象,其内容被初始化为 0。const buffer = new ArrayBuffer(32);
复制代码
上面代码表示实例对象 buffer
占用 32 个字节。
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);
复制代码
图片来自 MDN
Blob
全称:Binary Large Object
(二进制大型对象)。
Blob
对象表示一个二进制文件的数据内容,一般用来读写文件,好比一个图片文件的内容就能够经过 Blob
对象读写。
与 ArrayBuffer
区别:
Blob
用于操做二进制文件ArrayBuffer
用于操做内存浏览器原生提供 Blob()
构造函数,用来生成实例。
Blob
的内容由参数数组中给出的值的串联组成。
const leoBlob = new Blob(array [, options]);
复制代码
参数:
array
,必填,成员是字符串或二进制对象,表示新生成的Blob实例对象的内容;成员能够是一个由 ArrayBuffer
, ArrayBufferView
, Blob
, DOMString
等对象构成的 Array
,或者其余相似对象的混合体,它将会被放进 Blob
。DOMStrings
会被编码为UTF-8
。
options
,可选,是一个配置对象,这里介绍经常使用的属性 type
,表示数据的 MIME 类型,默认空字符串;options
目前可能有两个属性: type
和 endings
。
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'});
复制代码
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'}); // 获得 blob
leoBlob.size; // 38
leoBlob.type; // "text/html"
复制代码
Blob
实例方法:
clice
:方法用于建立一个包含源 Blob
的指定字节范围内的数据的新 Blob
对象。const newBlob = oldBlob.slice([start [, end [, contentType]]])
复制代码
包含三个参数:
start
,可选,起始的字节位置,默认 0;
end
,可选,结束的字节位置,默认 size
属性的值,不包含该位置;
contentType
,可选,新实例的数据类型(默认为空字符串);
图片来自 MDN
文件选择器 <input type="file">
用来让用户选取文件。出于安全考虑,浏览器不容许脚本自行设置这个控件的 value
属性,即文件必须是用户手动选取的,不能是脚本指定的。一旦用户选好了文件,脚本就能够读取这个文件。
文件选择器返回一个 FileList
对象,该对象是个类数组对象,每一个成员都是一个 File
实例对象。File
实例对象是一个特殊的 Blob
实例,增长了 name
和 lastModifiedDate
属性。
也包括拖放 API 的 dataTransfer.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 // 文件的最后修改时间
);
}
}
复制代码
在 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
对象。
浏览器容许使用 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,所以能够下载。
取得 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);
};
}
复制代码
本文首发在 pingan8787我的博客,如需转载请保留我的介绍。
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推荐 | github.com/pingan8787/… |
ES小册 | js.pingan8787.com |