Blob:
是浏览器环境上提供的一种大对象,通常是影像、声音或多媒体文件等原始数据的二进制对象,它和 ArrayBuffer 没有必然联系,但是又可以互相转化,Blob用于操作二进制文件,而 ArrayBuffer 用于操作内存。
详见Blob
const blob = new Blob( array, options );
var htmlFragment = ['hey!'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});
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);
}
}
}
<body>
<button onclick="download()">download.txt</button>
<script>
const getObjectURL = (file) => {
let url;
if (window.createObjectURL) {
url = window.createObjectURL(file);
} else if (window.URL) {
url = window.URL.createObjectURL(file);
} else if (window.webkitURL) {
url = window.webkitURL.createObjectURL(file);
}
return url;
};
function download() {
const fileName = 'download.txt';
const myBlob = new Blob(['johnYu'], { type: 'text/plain' });
downloadFun(fileName, myBlob);
}
function downloadFun(fileName, blob) {
const link = document.createElement('a');
link.href = getObjectURL(blob);
link.download = fileName;
link.click();
link.remove();
URL.revokeObjectURL(link.href);
}
</script>
</body>
// HTML 代码如下
//
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 // 文件的最后修改时间
);
}
}
function getBlob(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = function () {
callback(xhr.response);
}
xhr.send(null);
}
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);
}
}
}
<!-- html部分 -->
<input type="file" id='f' />
<!-- js部分 -->
<script>
function upload(blob) {
var xhr = new XMLHttpRequest();
xhr.open('POST', '/ajax', true);
xhr.setRequestHeader('Content-Type', 'text/plain')
xhr.send(blob);
}
document.getElementById('f').addEventListener('change', function (e) {
var blob = this.files[0];
const CHUNK_SIZE = 20; .
const SIZE = blob.size;
var start = 0;
var end = CHUNK_SIZE;
while (start < SIZE) {
upload(blob.slice(start, end));
start = end;
end = start + CHUNK_SIZE;
}
}, false);
</script>
var fileReader = new FileReader();
fileReader.readAsText(blob):返回文本,需要指定文本编码,默认为 UTF-8。
fileReader.readAsArrayBuffer(blob):返回 ArrayBuffer 对象。
fileReader.readAsDataURL(blob):返回 Data URL。
fileReader.readAsBinaryString(blob):返回原始的二进制字符串。
DataUrl:
允许内容的创建者将较小的文件嵌入到文档中。由于可以将其用作URL的替代,因此DataURL和BlobUrl一样可以在script/img/video/iframe等标签的src属性和background的url中使用,用法与BlobUrl基本一致
data:[][;base64],data
data:前缀
mediatype表明数据类型,是一个MIME类型字符串,如image/jpeg表示一个JPEG图片文件。如果省略,默认值为text/plain;charset=US-ASCII。
base64:标志位(如果是文本,则可选)
data:数据本身
atob(): 负责解码已经使用base64编码了的字符串。
btoa(): 将字符串转为base64编码的ASCII字符串。
btoa('foo ') // "PHhtbD5mb288L3htbD4="
atob('PHhtbD5mb288L3htbD4=') // "foo "
<script>
const createDownload = (fileName, content) => {
const blob = new Blob([content]);
const reader = new FileReader();
const link = document.createElement('a');
link.innerHTML = fileName;
link.download = fileName;
reader.onload = () => {
link.href = reader.result;
document.getElementsByTagName('body')[0].appendChild(link);
};
reader.readAsDataURL(blob);
};
createDownload('download.txt', 'johnYu');
</script>
DataUrl是直接编码的数据本身。关闭浏览器后仍然可以在地址栏访问,DataUrl由于数据本身由URL表示,因此可以将其保存在Cookie中传递给服务器
BlobUrl的长度一般比较短,但DataUrl因为直接存储图片base64编码后的数据,往往很长(Base64编码的数据体积通常会比二进制格式的图片体积大1/3。),因此当显式大图片时,使用BlobUrl能获取更好的可能性,速度和内存比DataUrl更有效
DataUrl不会被浏览器缓存,但是小部分会通过css缓存,如避免了让图片独自产生一次HTTP请求,不会每次使用时都加载一次
BlobUrl始终是唯一字符串,即时你每次传递相同的Blob,每次也会生成不同的BlobUrl;DataUrl值跟随blob变化;
ArrayBuffer:
是最基础的二进制对象,是对固定长度的连续内存空间的引用,存了一堆字节,也无法直接操作它。
//创建一个长度为8的ArrayBuffer,此时开辟一个固定8个字节的缓冲区也就是64位
var buffer = new ArrayBuffer(8);
//返回大小
buffer.byteLength //8
//复制一部分内存,slice用法和js相似
var buf2 = buf1.slice(0);
如果我们想操作这段内存空间怎么办呢?这时候就需要一个称之为视图的家伙
Uint8Array,Uint16Array,Uint32Array等这几个东西就是视图。你可以把它理解成 ArrayBuffer 的翻译器,只不过他们的翻译方式有点不同:
// 我们可以通过 BYTES_PER_ELEMENT 静态属性来得之视图单位的大小
const buf8 = new Uint8Array();
const buf16 = new Uint16Array();
const buf32 = new Uint32Array();
console.log(buf8.BYTES_PER_ELEMENT); // 1
console.log(buf16.BYTES_PER_ELEMENT); // 2
console.log(buf32.BYTES_PER_ELEMENT); // 4
// 创建8个字节长度的缓存冲
const buffer = new ArrayBuffer(8);
const uint8Array = new Uint8Array(buffer);
// log: [0, 0, 0, 0,0, 0, 0, 0]
console.log(uint8Array);
// 将buffer转化为Uint16Array
// Uint8Array中每一个元素表示两个字节(16位)
const uint16Array = new Uint16Array(buffer);
// log: Uint16Array(4) [ 0, 0, 0, 0 ]
console.log(uint16Array);
// 64位 8字节 -> 4个元素(log:4)
console.log(uint16Array.length);
//
new DataView(buffer [, byteOffset [, byteLength]])
// 创建8个字节长度的缓存冲
const buffer = new ArrayBuffer(8);
// 根据传入的buffer 从第一个字节开始,并且字节长度为匹配buffer的长度
const dataView = new DataView(buffer);
// 将DataView中偏移量为0个字节的字节,也就是第一个字节设置为十进制的1
dataView.setUint8(0, 1);
// 将DataView中偏移量为1个字节的字节,也就是第二个字节设置为十进制的2
dataView.setUint8(1, 2);
// 从dataView中偏移第0个字节,也就是第一个字节,获取8位
// log: 1
dataView.getUint8(0);
// 从dataView中偏移第一个字节获取八位,也就是获取第二个字节的值
// log: 2
dataView.getUint8(1);
// 偏移量为0个字节,获取后续16位大小(也就是获取前两个字节大小)
// log: 258
dataView.getUint16(0);
// 偏移量为2个字节,设置后16位大小为256(也就是设置第三个字节和第四个字节大小和为256)
dataView.setUint16(2, 256);
// 偏移量为2个字节,获取后16位大小
// log: 256
dataView.getUint16(2);
et xhr = new XMLHttpRequest();
xhr.open('GET', someUrl);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
let arrayBuffer = xhr.response;
// ···
};
xhr.send();
Buffer:
即缓存,去存储这些暂时用不上的数据(传的比 cpu 处理快,这个位置就存着提前到达的数据;比 cpu 处理慢,这个位置就存够一批足够能用的数据再给 cpu)这个区域就称之为缓存区(Buffer),一般是内存空间作为缓存空间。
node中的Buffer:
是 Uint8Array 类的子类,除了 Buffer 对象之外,Stream 和 Readline 也是比较常用的 node 内置二进制处理模块,使用这种二进制处理模块比常规的数组更快捷
// Node端(Koa)
const app = new Koa();
app.use(async (ctx, next) => {
if (ctx.path === '/ajax') {
const chunks = [];
const req = ctx.req;
req.on('data', buf => {
chunks.push(buf);
})
req.on('end', () => {
let buffer = Buffer.concat(chunks);
console.log(buffer.toString())
})
}
});
app.listen(3000)
// 前端
const xhr = new XMLHttpRequest();
xhr.open("POST", "ajax", true);
xhr.setRequestHeader('Content-Type', 'text/plain')
xhr.send("asdasdsadfsdfsadasdas");
运行结果
// 创建10个字节大小的空buffer
const buf1 = Buffer.alloc(10);
// 根据内容直接创建buffer
const buf2 = Buffer.from("hello buffer")
//将数据进行Unicode编码并展示
buf2.toJSON()
//buffer的大小
buf2.length //12
//写入数据到buffer
buf1.write("Buffer really rocks!")
//解码buffer
buf1.toString() // 'Buffer rea' buf1只有十个字节大小
关系及转换
var str = 'ab';
console.log(Uint8Array.from(str.split(''), (e) => e.charCodeAt(0))); // Uint8Array(2) [97, 98]
var u8 = Uint8Array.of(97, 98);
console.log(Array.from(u8, (e) => String.fromCharCode(e)).join('')); // ab
var str = 'ab';
console.log('data:application/octet-stream;base64,' + btoa(str)); // data:application/octet-stream;base64,YWI=
var data = 'data:application/octet-stream;base64,YWI=';
console.log(atob(data.split(',')[1])); // ab
var u8 = Uint8Array.of(1, 2);
console.log(u8.buffer); // ArrayBuffer(2) {}
var buffer = new ArrayBuffer(2);
console.log(new Uint8Array(buffer)); // Uint8Array(2) [0, 0]
var buffer = new ArrayBuffer(2);
var dataView = new DataView(buffer, 0); // DataView(2) {}
console.log(dataView.buffer); // ArrayBuffer(2) {}
var buffer = new ArrayBuffer(32);
var blob = new Blob([buffer]); // Blob {size: 32, type: ""}
var u8 = Uint8Array.of(97, 32, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33);
var blob = new Blob([u8]);
var blob = new Blob(['Hello World!'], {type: 'text/plain'}); // Blob {size: 12, type: "text/plain"}
var data = 'data:application/octet-stream;base64,YWI=';
function dataURLtoBlob(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 });
}
console.log(dataURLtoBlob(data)); // Blob {size: 2, type: "application/octet-stream"}