Blob、ArrayBuffer、File、FileReader、FormData这些名词总是经常看到,知道一点又好像不知道,像是同一个东西好像又不是,总是模模糊糊,最近终于下决心要弄清楚。
这些名词里:
因此,我们首先着重区分Blob、ArrayBuffer、File,然后再对fileReader和FormData做简要介绍。
binary large object
,表示二进制大对象,并不是前端的特有对象,而是计算机界的通用术语,MySql/Oracle数据库中,就有一种Blob类型,专门存放二进制数据。简单来说,Blob就是一个只读的二进制文件,我们可以知道它的文件大小(size),文件类型(type),并可以对其作出分割(slice)。
构造函数
直接通过new Blob()
就可以创建一个Blob对象
var aBlob = new Blob( array, options );
array(可选):是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体。(暂时可以不用理解,就可以看作是一堆数据) options(可选):一个对象,用来设置Blob的一些属性。主要的是一个type属性,表示Blob的类型(其他暂时也不用管)。
简单来说,就是可以通过向new Blob()传一堆数据,生成一个Blob对象
属性
方法
Blob只有一个slice方法,实现对文件的分割(注意这里并不违背Blob的只读性,slice只是只是复制指定范围内的Blob数据)。
Blob.slice(start, end ,contentType)
start:开始索引,可以为负数,语法类似于数组的slice方法。默认值为0。 end:结束索引,可以为负数,语法类似于数组的slice方法。默认值为最后一个索引。 contentType:新的Blob对象的MIME类型,这个值将会成为新的Blob对象的type属性的值,默认为一个空字符串。
//将base64转换为blob
dataURLtoBlob: function (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});
},
//将blob转换为file
blobToFile: function (theBlob, fileName) {
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
},
function saveShareContent (content, fileName) {
let downLink = document.createElement('a')
downLink.download = fileName
//字符内容转换为blod地址
let blob = new Blob([content])
downLink.href = URL.createObjectURL(blob)
// 链接插入到页面
document.body.appendChild(downLink)
downLink.click()
// 移除下载链接
document.body.removeChild(downLink)
}
content
是需要下载的内容fileName
是保存的文件的名字
原理就是利用Blob
对象把需要下载的内容转换为二进制,然后借助<a>
标签的href
属性和download
属性,实现下载。
ArrayBuffer的概念和用法相对比较复杂(它本身不复杂,只是使用方式比较丰富),之后会在另外一篇博客作出解释,这里仅做简要说明,主要是理解它的宏观概念。
Blob与ArrayBuffer的关系
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。
在v6.0之前创建Buffer对象直接使用new Buffer()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大,可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里面建议使用 Buffer.from() 接口去创建Buffer对象。
Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。
const buf = Buffer.from('runoob', 'ascii');
// 输出 72756e6f6f62
console.log(buf.toString('hex'));
// 输出 cnVub29i
console.log(buf.toString('base64'));
Node.js 目前支持的字符编码包括:
Buffer 提供了以下 API 来创建 Buffer 类:
// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 创建一个长度为 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据,
// 因此需要使用 fill() 或 write() 重写。
const buf3 = Buffer.allocUnsafe(10);
// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');
// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');
写入 Node 缓冲区的语法如下所示:
buf.write(string[, offset[, length]][, encoding])
参数描述如下:
根据 encoding 的字符编码写入 string 到 buf 中的 offset 位置。 length 参数是写入的字节数。 如果 buf 没有足够的空间保存整个字符串,则只会写入 string 的一部分。 只部分解码的字符不会被写入。
返回实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串。
buf = Buffer.alloc(256);
len = buf.write("www.psvmc.cn");
console.log("写入字节数 : "+ len);
执行以上代码,输出结果为:
$node main.js
写入字节数 : 14
let reader = new FileReader();
reader.onload = function () {
let buffer = Buffer.from(reader.result);
};
reader.readAsArrayBuffer(blob);
<input type="file">
选择的FileList对象,或者是使用拖拽操作搞出的DataTransfer对象。File就是Blob里面的一个小类,继承Blob的方法和属性,拥有自己特有的属性。通常表示<input type="file">
里的fileList对象
这里就不做过多介绍了,可以直接参考MDN上的介绍
//将blob转换为file
blobToFile: function (theBlob, fileName) {
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
利用FileReader结合Node.js保存Blob为本地文件
saveMedia = (blob) => {
let reader = new FileReader();
let filename = this.mediaOutputPath + "/" + this.getnowstr() + "_vedio.webm";
reader.onload = function () {
let buffer = Buffer.from(reader.result);
const fs = require('fs')
fs.writeFile(filename, buffer, {}, (err, res) => {
if (err) {
console.error(err);
return
}
})
};
reader.readAsArrayBuffer(blob);
};
准确来说,FormData其实与上述内容关系就不大了。它是XMLHttpRequest Level 2添加的一个新的接口,我们可以通过JavaScript用一些键值对来模拟一系列表单控件。FormData的最大优点就是,比起普通的ajax, 使用FormData我们可以异步上传一个二进制文件,而这个二进制文件,就是我们上面讲的Blob对象。