BLOB详解
BLOB
是Binary Large Object
的缩写,意为“大的二进制对象”。
《JavaScript权威指南》中对BLOB的描述:
A Blob is an opaque reference to, or handle for, a chunk of data. Blobs oten represent chunks of data from an external source such as a local file, a URL, or a database.
BLOB的两个特点:
- large: Blob表示巨大的数据块,如视频文件
- opaque(不透明): 我们对BLOB可以做到操作仅限于设置字节长度、获取MIME类型、截取更小的BLOB。

获取Blob的方式:
1. Blob支持结构化克隆算法(structured clone algorithm),所以可以通过消息事件从另外一个窗口或线程中获取blob对象
2. 从客户端数据库取出blob
3. 通过http从网络上下载blob
function getBlob(url, callback){
let xhr = new XMLHTTPRequest();
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.onload = function() {
callback(xhr.response); // 注意,是 .response 而不是 .responseText
}
// 如果下载的blob很大,可以使用 onprogress 获取下载进度
xhr.send(null);
}
4. 通过BlobBuilder
创建新的blob对象
var bb = new BlobBuilder();
bb.append('this blob contains this text and 10 big-endian 32-bit signed ints.'); // 写入字符串
bb.append('\0'); // 写入空字符,表示字符串已结束
var arraybuffer = new ArrayBuffer(4*10);
var dataView = new DataView(arrayBuffer);
for(var i=0; i<10; i++){
dataView.setInt32(i*4, i);
}
bb.append(arrayBuffer); // 写入ArrayBuffer
var blob = bb.getBlob('x-optional/mime-type-here'); // 获取blob,并指定mime类型
5. 客户端JS中的File
对象是BLob的子类型。File是一个有名称(name)和修改日期(lastModifiedDate)属性的Blob数据。可以通过<input type="file">
元素标签或者拖拽接口获取File对象。
<input type="file" id="ele">
const selectedFiles = document.getElementById("ele").files
// files属性是的值是一个File对象数组,包含用户选择的0个或多个文件的file对象。
for (let i = 0; i < selectedFiles.length; i++) {
const f = selectedFiles[i]
console.log(f.name, f.lastModifiedDate)
console.log(f.size, f.type) // Blob对象的属性
}
对Blob对象可做如下操作:
1. 创建Blob URL
Blob url 是指向存储在浏览器缓存或磁盘中的blob的一个引用。
通过createObjectURL()
获取指向Blob数据的url blob://
,并且在DOM、css中使用blob url,用法和普通的url一样。
Blob URL 受同源策略限制,只有在同源的document中是合法的。
Blob URL不是不变的,创建Blob URL的document被用户关闭后,Blob URL就会变成无效的。
blob://URL
工作方式和http://URL
类似,当请求blob://URL
时浏览器行为和http请求相同。如果请求的blob url不再合法,浏览器必须返回404(Not Found)状态码。当请求不同源的blob url时,浏览器必须返回403(Not Allowed)。
Blob URL 只允许通过 GET
请求,请求成功需要返回状态码200,并且response.header.Content-Type = Blob.type
下面的代码是通过blob url预览拖拽到指定区域的图片文件。
<!DOCTYPE html>
<html>
<head>
<script>
// 处理浏览器兼容问题
var getBlobURL = (window.URL && URL.createObjectURL.bind(URL)) ||
(window.webkitURL && webkitURL.createObjectURL.bind(URL)) ||
window.createObjectURL;
// 释放之前通过createObjectURL创建的对象
var revokeBlobURL = (window.URL && URL.revokeObjectURL.bind(URL)) ||
(window.webkitURL && webkitURL.revokeObjectURL.bind(URL)) ||
window.revokeObjectURL;
window.onload = function(){
var droptarget = document.getElementById('droptarget');
droptarget.ondragenter = function (e) {
var types = e.dataTransfer.types;
if (!types ||
(types.contains && types.contains('Files')) ||
(types.indexOf && types.indexOf('Files') !== -1)
){
droptarget.classList.add('active');
return false;
}
};
droptarget.ondragleave = function () {
droptarget.classList.remove('active');
};
droptarget.ondragover = function(e) {
return false;
};
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 = getBlobURL(files[i]);
img.onload = function () {
this.width = 100;
document.body.append(this);
revokeBlobURL(this.src); // 防止内存泄漏
}
}
droptarget.classList.remove('active');
return false;
}
}
</script>
<style>
#droptarget {border: solid black 2px; width: 200px; height: 200px;}
#droptarget.active {border: solid red 4px;}
</style>
</head>
<body>
<div id="droptarget">Drop Files Here</div>
</body>
</html>
-
通过
postMessage()
在窗口和工作进程间传输blob数据 -
将blob存储在客户端数据库
-
通过XMLHTTPRequest的
send()
方法将blob上传到服务器
5. FileReader
对象的异步接口以string
或ArrayBuffer
的形式提取blob对象的内容。
因为Blob的体积比较大,所有访问磁盘上的blob的相关API都是异步的。
function readfile(f){
var reader = new FileReader();
reader.readAsText(f);
reader.onload = function () {
var text = reader.result;
console.log('file content: ', text);
}
reader.onerror = function(e){
console.log('Error', e);
}
}
- 通过
Filesystem API
和FileWriter
对象将Blob对象写到本地文件,相关接口浏览器暂不支持。
转载自:https://juejin.cn/post/6844903919823355911