Blob是什么

395 阅读3分钟

Blob介绍

blob表示二进制大对象(binary larget object),是一个不可变、原始数据的类文件对象。同时Blob还是File的超类。

可能这么说有点模糊,我们可以把blob理解为使用二进制保存数据的对象,这个对象保存的数据可以是很多内容,例如字符串、ArrayBuffer、ArrayBufferView、Domstring,甚至是其他的blob都可以,它们以二进制的形式保存在blob中,但是不同于ArrayBuffer,ArrayBuffer中的二进制数据可以通过TypeArray或者DataView写入修改,Blob中的二进制数据是不可修改的。

Blob API

构造函数

语法:

var aBlob = new Blob( array, options );

Blob()构造函数接收两个参数:

  • array:是一个由字符串、ArrayBuffer、ArrayBufferView、Domstring等对象组成的Array。
  • options :是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
    • type:指定被放入到 blob 中的数组内容的 MIME 类型,默认值是""
    • endings:默认值为"transparent"。用于指定包含行结束符\n的字符串如何被写入。有两个值,一个是"native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,另一个是 "transparent",代表会保持 blob 中保存的结束符不变
//Domstring
const domString = new Blob(['<a id="a"></a>'], {type : 'text/html'});
//普通文本
const text=new Blob(['这是一段文字'],{type:"text/plain"})
//ArrayBuffer
const bufferBlob=new Blob([new ArrayBuffer(12)])

实例属性

通过Blob()构造函数创建的实例拥有两个属性:

  • size:字节大小
  • type:实例的MIME类型

实例方法

Blob实例上有四个方法

  • text():返回一个promise对象,以 resolve 状态返回一个以文本形式包含 blob 中数据的 String对象

    const blob=new Blob(['这是一段文字'],{type:"text/plain"})
    const textPromise=blob.text()
    textPromise.then(text=>{
      console.log(text)//这是一段文字
      console.log(typeof(text))//string
    })
    
  • stream():返回一个ReadableStream对象。具体ReadableStream对象的使用可查看MDN文档

    const blob=new Blob(['这是一段文字'],{type:"text/plain"})
    const stream=blob.stream()
    console.log(stream)//ReadableStream对象
    
  • arrayBuffer():返回一个 resolve 状态的promise对象,resolveValue是一个ArrayBuffer对象。

    const blob=new Blob(['这是一段文字'],{type:"text/plain"})
    const bufferPromise=blob.arrayBuffer()
    bufferPromise.then(buffer=>console.log(buffer))//ArrayBuffer
    
  • slice([start [, end [, contentType]]]):以指定字节范围复制blob的数据,并返回一个blob实例。start是开始字节位置,end是结束字节位置(包括),contentType可以给返回的blob实例指定type

    const blob=new Blob(['这是一段文字'],{type:"text/plain"})
    const other=blob.slice(0,3,"text/plain")
    other.text().then(res=>console.log(res))//这
    

应用场景

图片预览

我们通常会遇到这样一个场景:用户预览本地选择的图片。通常我们有两种方法实现:

  • 通过FileReader的readAsDataURL来实现
  • 利用URL.createObjectURL()。这个函数可以传入File对象或者Blob对象,返回一个指向内存中地址的URL字符串。
const input = document.createElement("input")
input.type="file"
input.onchange=(e)=>{
  const file=input.files[0]
  const url=URL.createObjectURL(file)
  //将url放到image标签上即可显示图片
  URL.revokeObjectURL(file)
}
document.body.append(input)

下载文件

利用a标签下载文件

const button=document.createElement('button')
button.textContent="下载"
button.onclick=()=>{
  const blob=new Blob(['这是一段文本内容'],{type:"text/plain"})
  const a=document.createElement('a')
  a.href=URL.createObjectURL(blob)
  a.download="blob.txt"
  a.click()
  a.remove()
  URL.revokeObjectURL(blob)
}
document.body.append(button)

分片上传

针对大文件的上传,我们可以利用blob的slice方法将数据切割上传。

const file = new Blob(["a".repeat(100000)], {type:"text/plain"});

const size = 10000;
const url = "https://httpbin.org/post";

async function chunkedUpload() {
  for (let start = 0; start < file.size; start += size) {
      const chunk = file.slice(start+1, start + size);
      const fd = new FormData();
      fd.append("data", chunk);

      await fetch(url, { method: "post", body: fd }).then((res) =>
        res.text()
      );
  }
}

对象转换

Blob和ArrayBuffer转换

Blob--->ArrayBuffer:

const blob=new Blob(['这是一段文字'],{type:"text/plain"})
//利用FileReader
const read=new FileReader()
read.readAsArrayBuffer(blob)
read.onload=()=>{
  console.log(read.result)//ArrayBuffer
}
//利用Blob.arrayBuffer()
const bufferPromise=blob.arrayBuffer()
bufferPromise.then(buffer=>{
  console.log(buffer)//ArrayBuffer
})

ArrayBuffer--->Blob:

//通过Blob()构造函数
const buffer=new ArrayBuffer(8)
const blob=new Blob([buffer])