Blob 对象表示一个不可变、原始数据类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

一、构造方法

Blob() 构造函数返回一个新的 Blob 对象。 blob的内容由参数数组中给出的值的串联组成。
语法:

  1. var aBlob = new Blob( array, options );

参数:

array array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8。
options options 是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
- type,默认值为 "",它代表了将会被放入到blob中的数组内容的MIME类型。
- endings``(未标准化),默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: "native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持blob中保存的结束符不变

测试1:使用DOMString创建Blob对象

MDN[https://developer.mozilla.org/zh-CN/docs/Web/API/Blob/Blob]参考示例如下:

        var aFileParts = ['<a id="a"><b id="b">hey!</b></a>']; // 一个包含DOMString的数组
        var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
        console.log(oMyBlob);

控制台打印:
image.png
以上测试可以看到,第二个参数中的 type 数据类型在 Blob 创建后就成了 Blob对象的类型 blob.type的值。其实学到现在,还是不知道Blob到底用来干啥。猜想就是用来处理文件的吧,例如下载文件时设置 responseType 为 blob,然后前端直接使用 a 标签 download 来实现文件下载。或者是,直接在 js 中生成一个文件,在不走后台的情况下实现页面的某些数据生成文件?以下尝试从当前页面中将 js 脚本弄成文件下载下来,后续可以考虑用这个做点有意思的东西。

测试2:使用Blob将当前的网页脚本下载到一个文件

        var scripts = document.scripts; //拿到所有的脚本
        var lastScript = scripts[scripts.length -1]; //取最后一个脚本标签
        var scriptText = lastScript.innerHTML; //获取脚本标签中的内容
        var oMyBlob = new Blob([scriptText], {type : 'text/javascript'}); // 得到 blob

        //使用a标签的download实现下载
        var a = document.createElement("a");
        a.download = "thisPageScript.js";
        a.style.display = "none";
        a.href = URL.createObjectURL(oMyBlob);
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a)

触发上面的代码,可以下载一个名为: thisPageScript.js 的文件,打开后文件如下:
image.png

测试3:ArrayBuffer, ArrayBufferView (待补充)

这两个接口还搞不清楚,后续补充测试 @TODO

二、方法

Blob 对象共有四个方法,分别是arrayBuffer()、slice()、stream()、text()

2.1 arrayBuffer()

arrayBuffer() 方法返回一个 Promise 对象,包含 blob 中的数据,并在 ArrayBuffer 中以二进制数据的形式呈现。
语法:

var bufferPromise = blob.arrayBuffer();

blob.arrayBuffer().then(buffer => /* 处理 ArrayBuffer 数据的代码……*/);

var buffer = await blob.arrayBuffer();

参数:
无参数
返回值:
返回一个 promise 对象,在 resolved 状态中以二进制的形式包含 blob 中的数据,并呈现在 ArrayBuffer 中。

测试1 :将Blob 对象转成 arraybuffer

        var aFileParts = ['<a id="a"><b id="b">hey!</b></a>']; // 一个包含DOMString的数组
        var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
        oMyBlob.arrayBuffer().then(buffer => {
            console.log(buffer);
        })

控制台打印:
image.png

2.2 slice()

slice() 方法用于创建一个包含源 Blob的指定字节范围内的数据的新 Blob 对象。
语法:

var blob = instanceOfBlob.slice([start [, end [, contentType]]]};

参数:

start(可选) 这个参数代表 Blob 里的下标,表示第一个会被会被拷贝进新的 Blob 的字节的起始位置。如果你传入的是一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。举例来说, -10 将会是 Blob 的倒数第十个字节。它的默认值是0, 如果你传入的start的长度大于源 Blob 的长度,那么返回的将会是一个长度为0并且不包含任何数据的一个 Blob 对象。
end(可选) 这个参数代表的是 Blob 的一个下标,这个下标-1的对应的字节将会是被拷贝进新的Blob 的最后一个字节。如果你传入了一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。举例来说, -10 将会是 Blob 的倒数第十个字节。它的默认值就是它的原始长度(size).
contentType(可选) 给新的 Blob 赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是一个空的字符串。

返回值:
一个新的 Blob 对象,它包含了原始 Blob 对象的某一个段的数据。

测试:slice()

        var aFileParts = ['测试slice获取一部分的内容']; // 一个包含DOMString的数组
        var blob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
        var newBlob = blob.slice(0,6);

        blob.text().then(blobText => {
            console.log("blobText:",blobText)
        })
        newBlob.text().then(newBlobText => {
            console.log("newBlobText:", newBlobText)
        })

控制台:
image.png

2.3 stream()

stream() 方法返回一个ReadableStream对象,读取它将返回包含在Blob中的数据。
语法:

var stream = blob.stream();

参数:
无参数
返回值:
一个ReadableStream对象,读取后返回 Blob的内容。
使用说明:
使用 stream() 函数与其返回的ReadableStream对象,你将得到一些有趣的能力:

  • 调用ReadableStream的方法getReader(),返回一个 ReadableStreamDefaultReader 对象,这个对象有一个read()方法,可以用于读取 Blob对象
  • 调用返回ReadableStream对象的pipeTo()方法将blob对象的数据传输到可写流WritableStream 。
  • 调用返回stream对象的tee()方法以准备可读流。该方法会返回一个数组,该数组包含两个新的 ReadableStream 对象,每个对象都会返回 Blob的内容。
  • 调用返回stream对象的pipeThrough()方法,通过一个TransformStream对象或其它任意可读可写对传输流对象。

    测试:stream()。 额!不知道有啥用?

          var aFileParts = ['测试stream返回流']; // 一个包含DOMString的数组
          var blob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
          var stream = blob.stream();
    
          //读取Blob
          stream.getReader().read().then(res => {
              console.log(res)
          })
          //将Blob对象转到可写流
          var ws = new WritableStream();
          stream.pipeTo(ws);
          ws.getWriter().write().then(res => {
              console.log(res)
          })
    

    2.4 text()

    text()方法返回一个 Promise 对象,包含 blob 中的内容,使用 UTF-8 格式编码。
    语法: ```javascript var textPromise = blob.text();

blob.text().then(text => / 执行的操作…… /);

var text = await blob.text();

**参数:**<br />无参数<br />**返回值:**<br />返回一个 promise 对象,以 resolve 状态返回一个以文本形式包含 blob 中数据的 USVString。并且该数据总是被识别为 UTF-8 格式。<br />**使用说明:**<br />FileReader 的 readAsText() 方法是一个与之类似的方法,它对 Blob 和 File 对象都适用。下面是两个主要的不同之处:

- Blob.text() 返回的是一个 promise 对象,而 FileReader.readAsText() 是一个基于事件的 API。
- Blob.text() 总是使用 UTF-8 进行编码,而 FileReader.readAsText() 可以使用不同编码方式,取决于 blob 的类型和一个指定的编码名称。
<a name="L5bps"></a>
#### 测试:text()
```javascript
        var aFileParts = ['测试text']; // 一个包含DOMString的数组
        var blob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
        blob.text().then(res => {
            console.log(res)
        })

控制台:
image.png

三、属性

3.1 size

返回一个File对象所指代的文件的大小,单位为字节。

3.2 type

Blob 对象的 type 属性给出文件的 MIME 类型。如果类型无法确定,则返回空字符串。
语法:

var textPromise = blob.text();

blob.text().then(text => /* 执行的操作…… */);

var text = await blob.text();

返回值:
字符串
测试:

    var aFileParts = ['测试text']; // 一个包含DOMString的数组
        var blob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
        console.log("new 的Blob:",blob.type);

        var files = $("#test-type")[0].files;
        for (var i = 0; i < files.length; i++) {
            console.log("file:", files[i].type)
        }

控制台
image.png