Blob
对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。
File
接口基于
Blob
,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
ArrayBuffer
ArrayBuffer
对象用来表示通用的、固定长度的原始二进制数据缓冲区。
它是一个字节数组,通常在其他语言中称为“byte array”。
你不能直接操作
**ArrayBuffer**
的内容,而是要通过
类型数组对象
或
**DataView**
对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容
。
总结:要操作二进制,首先需要把二进制数据放在一个地方,ArrayBuffer就是充当这样一个容器的作用。
区别:Blob与ArrayBuffer的区别在于,Blob是不可变的数据,而ArrayBuffer是可以编辑的。
类型化数组(TypedArray 对象)
单个元素值的范围
大小(bytes)
Web IDL 类型
C 语言中的等价类型
Int8Array
-128
to
127
8 位二进制有符号整数
int8_t
Uint8Array
0
to
255
8 位无符号整数(超出范围后从另一边界循环)
octet
uint8_t
Uint8ClampedArray
0
to
255
8 位无符号整数(超出范围后为边界值)
octet
uint8_t
Int16Array
-32768
to
32767
16 位二进制有符号整数
short
int16_t
Uint16Array
0
to
65535
16 位无符号整数
unsigned short
uint16_t
Int32Array
-2147483648
to
2147483647
32 位二进制有符号整数
int32_t
Uint32Array
0
to
4294967295
32 位无符号整数
unsigned long
uint32_t
Float32Array
1.2
×
10-38
to
3.4
×
1038
32 位 IEEE 浮点数(7 位有效数字,如
1.1234567
)
unrestricted float
float
Float64Array
5.0
×
10-324
to
1.8
×
10308
64 位 IEEE 浮点数(16 有效数字,如
1.123...15
)
unrestricted double
double
BigInt64Array
-263
to
263-1
64 位二进制有符号整数
bigint
int64_t (signed long long)
BigUint64Array
0
to
264-1
64 位无符号整数
Int8Array是8 位二进制有符号整数,Uint8Array是8 位无符号整数,其中有符号的意思是数组中的元素可以存在符号,即可以是负数。
var ui= new Uint8Array([1, -2, 3]);
console.log(ui);
var Int= new Int8Array([1, -2, 3]);
console.log(Int);
Uint8Array表示数组中每个元素占8位(1个字节),Uint16Array表示数组中每个元素占16位(2个字节)。
var ui8= new Uint8Array([1, -2, 3, 4]);
var ui16= new Uint16Array([1, 3]);
console.log(ui8.byteLength);
console.log(ui16.byteLength);
每一种视图都有一个BYTES_PER_ELEMENT常数,表示这种数据类型占据的字节数。刚好验证了上面。
Uint8Array.BYTES_PER_ELEMENT
Uint16Array.BYTES_PER_ELEMENT
为什么会有Blob
一直以来,JS都没有比较好的可以直接处理二进制的方法。而blob的存在,允许我们可以通过js直接操作二进制数据。
生成Blob
var aBlob = new Blob( array, options )
array
是一个由ArrayBuffer
, ArrayBufferView
, Blob
, DOMString
等对象构成的 Array
,或者其他类似对象的混合体,它将会被放进 Blob
。DOMStrings会被编码为UTF-8。
options
是一个可选的BlobPropertyBag
字典,它可能会指定如下两个属性:
type
,默认值为 ""
,它代表了将会被放入到blob中的数组内容的MIME类型。
endings
,默认值为"transparent"
,用于指定包含行结束符\n
的字符串如何被写入。 它是以下两个值中的一个: "native"
,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent"
,代表会保持blob中保存的结束符不变
生成ArrayBuffer
var arrayBuffer=new ArrayBuffer(length)
length
要创建的 ArrayBuffer
的大小,单位为字节。
一个指定大小的 ArrayBuffer
对象,其内容被初始化为 0。
字符串blob
var aBlob=new Blob(['春']);
console.log(aBlob);//Blob(3) {size: 3, type: ""}
var bBlob=new Blob(['a']);
console.log(bBlob);//Blob(1) {size: 1, type: ""}
从我的第一篇文章中可以知道一个中文的UTF-8占三个字节,原始的ASCll码只占用一个字节,
从上面的结果可以就可以验证这一点。
创建ArrayBuffer对象
const buffer = new ArrayBuffer(3);
console.log(buffer.byteLength);
判断是否是视图实例(类型数组对象或 DataView 对象)
console.log(ArrayBuffer.isView(new Int8Array()));
console.log(ArrayBuffer.isView(new Uint32Array(3)));
console.log(ArrayBuffer.isView(new Blob()));
操作ArrayBuffer
类型数组对象操作
创建了一个 4字节的缓冲区,并使用一个Unit8Array(视图实例)来引用它。ArrayBuffer表示了一段内存,但是却没有规定如何分隔里面的内容。比如用Unit8Array引用就表示8位一分隔,Unit16Array表示16位一分隔。
var buffer=new ArrayBuffer(4);
console.log(buffer);
var bytes = new Uint8Array( buffer );
var Int=new Uint16Array(buffer);
console.log(bytes);
console.log(Int);
这个也就是我第三篇文章中ArrayBuffer转base64操作所用的方法。
DataView操作
var buffer= new ArrayBuffer(16)
var view= new DataView(buffer)
view.setUint8(1,20)
view.getUint8(1)
dataview.getUint8(byteOffset [, littleEndian])
参数解析:
(1).byteOffset:必需,从哪个字节开始读取数据,0表示第一个字节,以此类推。
(2).littleEndian:可选,布尔值,规定是大端字节序还是小端字节序;true表示小端字节序,省略或者false表示大端字节序。
总结:计算机默认使用小端字节序,所以使用DataView读取Unit16Array的时候要使用view.getUint16(0,true)。
区别:类数组和DataView操作的区别在于,类数组操作会有字节序问题,而DataView可以指定字节序。
类数组对象转ArrayBuffer
var bytes
= new Uint8Array([1,2,3])
var buf=bytes.buffer
console.log(buf)
var bytes = new Uint8Array([1,2,2,3]);
var buf=bytes.buffer;
var ui8 = new Uint8Array(buf);
console.log(ui8);
var ui16 = new Uint16Array(buf);
console.log(ui16);
var view=new DataView(buf);
console.log(view.getUint8(0));
console.log(view.getUint16(0,true));
1, 2, 2,3 (十进制)
00000001, 00000010, 00000010,00000011 (二进制)
513,770(十进制)
1000000001,1100000010(二进制)
上面可以看出513这个 2 字节的数据,其实是把 1
和 2
这两个挨着的 1 字节的数据,以 倒序 方式拼接在一起的。也就是字节序。
Blob转ArrayBuffer
var blob=new Blob(['春节']),fileReader=new FileReader();
fileReader.onload=function(e){
console.log(this.result);
fileReader.readAsArrayBuffer(blob);
var blob=new Blob(['春节']);
blob.arrayBuffer().then(res=>{console.log(res)})
ArrayBuffer转Blob
var blob=new Blob(['春节']),fileReader=new FileReader(),buffer
fileReader.onload=function(e){
console.log(this.result)
buffer=this.result
var newBlob=new Blob([buffer])
newBlob.text().then(res=>{console.log(res)})//春节
fileReader.readAsArrayBuffer(blob)
Blob应用
1.Data URL:表示base64 编码的图像数据。
可以看我上一篇文章有blob转base64显示的示例。
2.HTTP URL:表示从服务器上获取图片。
<img data-v-391f1edb="" src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-assets/v3/static/img/collections.945b9ae.png~tplv-t2oaga2asx-image.image" class="icon">
3.Object URL:用来代表存储在浏览器内存中的 File
或 Blob
对象。Object URL 可以由createObjectURL
API 来创建,并由 revokeObjectURL
API 释放。
// 掘金首页收藏集图片
fetch('https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-assets/v3/static/img/collections.945b9ae.png~tplv-t2oaga2asx-image.image',{
method: 'get',
responseType: 'blob'
}).then(res =>res.blob()).then(res=> {
var herf=URL.createObjectURL(res)
console.log(href)
//替换相应的url也能够显示图片
URL.revokeObjectURL(herf)
//<img data-v-391f1edb="" src="blob:https://juejin.im/c6322385-2ed5-47de-8dd4-9faa5acd4eb4" class="icon">
获取上传 Input 中的图片对象 File
图片通过 Canvas 转换压缩,这里会用到的 Canvas 的 drawImage 以及 toDataURL 这两个 Api,一个调节图片的分辨率的,一个是调节图片压缩质量。
//为了演示,用获取的blob代替从input对象获取的File对象
var image = new Image(); //新建一个img标签;
fetch('p1-jj.byteimg.com/tos-cn-i-t2…', {
method: 'get',
responseType: 'blob'
}).then(res => res.blob()).then(res => {
console.log(res);//Blob(833) {size: 833, type: "image/png"}
var href = URL.createObjectURL(res);
image.src = href;
image.onload = function() {
compress(image, 'png', 92,100); //canvas压缩百分之92;图片保存原有大小
function compress(image, type, quality,targetPercent) {
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
// 定义 canvas 大小,也就是压缩后下载的图片大小
let imageWidth = image.width; //压缩后图片的大小
let imageHeight = image.height;
canvas.width = imageWidthtargetPercent/100;
canvas.height = imageHeighttargetPercent/100;
context.drawImage(image, 0, 0,canvas.width,canvas.height);
var compressImg = canvas.toDataURL(image/${type}
, quality / 100);
console.log(compressImg); //base64数据;
canvas.toBlob(function(blob) {//canvas转blob;
console.log(blob);//Blob(725) {size: 725, type: "image/png"}
toDataURL()
方法,该方法接收 type
和 encoderOptions
两个可选参数。
其中 type
表示图片格式,默认为 image/png
。而 encoderOptions
用于表示图片的质量,在指定图片格式为 image/jpeg
或 image/webp
的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92
,其他参数会被忽略。
图片压缩到指定大小
fetch('https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-assets/v3/static/img/collections.945b9ae.png~tplv-t2oaga2asx-image.image', {
method: 'get',
responseType: 'blob'
}).then(res => res.blob()).then(res => {
console.log(res.size)
var image = new Image()
var href = URL.createObjectURL(res)
image.src = href
compress(image,res,1)
//base64转blob
function dataURLtoBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1])
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
var ab = new ArrayBuffer(byteString.length)
var ia = new Uint8Array(ab)
for (var i = 0
ia[i] = byteString.charCodeAt(i)
return new Blob([ab], {type: mimeString})
function compress(image,blob,size) {
//blob原始的流 size要压缩的流的大小
let oldSize=blob.size
if(oldSize>size*1024*1024){//大于1M才压缩
let canvas = document.createElement('canvas')
let context = canvas.getContext('2d')
// 定义 canvas 大小,也就是压缩后下载的图片大小
let imageWidth = image.width
let imageHeight = image.height
let targetPercent=(size*1024*1024/oldSize).toFixed(2)
canvas.width = imageWidth*targetPercent
canvas.height = imageHeight*targetPercent
context.drawImage(image, 0, 0,canvas.width,canvas.height)
var compressImg = canvas.toDataURL(blob.type,1)
return dataURLtoBlob(compressImg)
}else{
return blob
const file = new File(["a".repeat(1000000)], "test.txt")
const chunkSize = 40000
const url = "https://httpbin.org/post"
async function chunkedUpload() {
for (let start = 0
const chunk = file.slice(start, start + chunkSize + 1)
const fd = new FormData()
fd.append("data", chunk)
await fetch(url, { method: "post", body: fd }).then((res) =>
res.text()
var url = 'https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-assets/v3/static/img/collections.945b9ae.png~tplv-t2oaga2asx-image.image'; //文件下载地址fetch(url, { method: 'get', responseType: 'blob'}).then(res => res.blob()).then(res => { var url = window.URL.createObjectURL(res); var a = document.createElement("a"); a.href = url; a.download = "测试"; a.click(); a.remove(); window.URL.revokeObjectURL(url);})
你不知道的 Blob
前端通过Blob实现文件下载
MDN | Blob
JavaScript
- 3719
-
hjylxmhzq
JavaScript