文章简介
本篇文章为【JavaScript 漫游】专栏的第 040 篇文章,对浏览器模型中的 Blob 对象进行了总结。
概述
Blob 对象表示一个二进制文件的数据内容,比如一个图片文件的内容就可以通过 Blob 对象读写。它通常用来读写文件,它的名字是 Binary Large Object(二进制大型对象)的缩写。
浏览器原生提供 Blob()
构造函数,用来生成实例对象。
new Blob(array, [, options]);
Blob
构造函数接受两个参数。第一个参数是数组,成员是字符串或二进制对象,表示新生成的 Blob
实例对象的内容;第二个参数是可选的,是一个配置对象,目前只有一个属性 type
,它的值是一个字符串,表示类型的 MIME 类型,默认是空字符串。
var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});
var obj = { hello: 'world' };
var blob = new Blob([ JSON.stringify(obj) ], {type : 'application/json'});
实例属性和实例方法
Blob
具有两个实例属性 size
和 type
,分别返回数据的大小和类型。
var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});myBlob.size // 32
myBlob.type // "text/html"
Blob
具有一个实例方法 slice
,用来拷贝原来的数据,返回的也是一个 Blob
实例。
myBlob.slice(start, end, contentType); // contentType: 新实例的数据类型,默认为空字符串
获取文件信息
文件选择器 <input type="file">
用来让用户选取文件。出于安全考虑,浏览器不允许脚本自行设置这个控件的 value
属性,即文件必须是用户手动选取的,不能是脚本指定的。一旦用户选好了文件,脚本就可以读取这个文件。
文件选择器返回一个 FileList 对象,该对象是一个类似数组的成员,每个成员都是一个 File 实例对象。File 实例对象是一个特殊的 Blob 实例,增加了 name
和 lastModifiedDate
属性。
// HTML 代码如下
// <input type="file" accept="image/*" multiple οnchange="fileinfo(this.files)"/>function fileinfo(files) {for (var i = 0; i < files.length; i++) {var f = files[i];console.log(f.name, // 文件名,不含路径f.size, // 文件大小,Blob 实例属性f.type, // 文件类型,Blob 实例属性f.lastModifiedDate // 文件的最后修改时间);}
}
除了文件选择器,拖放 API 的 dataTransfer.files
返回的也是一个FileList 对象,它的成员因此也是 File 实例对象。它的成员因此也是 File 实例对象。
下载文件
AJAX 请求时,如果指定 responseType
属性为 blob
,下载下来的就是一个 Blob 对象。
function getBlob(url, callback) {var xhr = new XMLHttpRequest();xhr.open('GET', url);xhr.responseType = 'blob';xhr.onload = function () {callback(xhr.response);}xhr.send(null);
}
生成 URL
浏览器允许使用 URL.createObjectURL()
,针对 Blob 对象生成一个临时 URL,以便于某些 API 使用。这个 URL 以 blob://
开头,表明对应一个 Blob 对象,协议头后面是一个识别符,用来唯一对应内存里面的 Blob 对象。
var droptarget = document.getElementById('droptarget');droptarget.ondrop = function (e) {var files = e.dataTransfer.files;for (var i = 0; i < files.length; i++) {var type = files[i].type;if (type.substring(0,6) !== 'image/')continue;var 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 对象。Blob 对象作为参数传入这些方法,然后以指定的格式返回。
FileReader.readAsText()
:返回文本,需要指定文本编码,默认为 UTF-8FileReader.readAsArrayBuffer()
:返回 ArrayBuffer 对象FileReader.readAsDataURL()
:返回 Data URLFileReader.readAsBinaryString()
:返回原始的二进制字符串
// HTML 代码如下
// <input type=’file' οnchange='readfile(this.files[0])'></input>
// <pre id='output'></pre>
function readfile(f) {var reader = new FileReader();reader.readAsText(f);reader.onload = function () {var text = reader.result;var out = document.getElementById('output');out.innerHTML = '';out.appendChild(document.createTextNode(text));}reader.onerror = function(e) {console.log('Error', e);};
}
上面代码中,通过指定 FileReader 实例对象的 onload
监听函数,在实例的 result
属性上拿到文件内容。
// HTML 代码如下
// <input type="file" οnchange="typefile(this.files[0])"></input>
function typefile(file) {// 文件开头的四个字节,生成一个 Blob 对象var slice = file.slice(0, 4);var reader = new FileReader();// 读取这四个字节reader.readAsArrayBuffer(slice);reader.onload = function (e) {var buffer = reader.result;// 将这四个字节的内容,视作一个32位整数var view = new DataView(buffer);var 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);};
}
上面是 FileReader.readAsArrayBuffer()
的例子,用于读取二进制文件。