2019-11-09 23:29:10 +08:00
|
|
|
|
# Blob
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2022-02-12 20:45:57 +08:00
|
|
|
|
`arrayBuffer` 和视图(view)都是 ECMA 标准的一部分,是 JavaScript 的一部分。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
在浏览器中,还有其他更高级的对象,特别是 `Blob`,在 [File API](https://www.w3.org/TR/FileAPI/) 中有相关描述。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
`Blob` 由一个可选的字符串 `type`(通常是 MIME 类型)和 `blobParts` 组成 —— 一系列其他 `Blob` 对象,字符串和 `BufferSource`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2019-07-29 16:04:58 +03:00
|
|
|
|

|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-09 10:25:34 +08:00
|
|
|
|
构造函数的语法为:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
|
new Blob(blobParts, options);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
- **`blobParts`** 是 `Blob`/`BufferSource`/`String` 类型的值的数组。
|
2019-11-08 22:53:33 +08:00
|
|
|
|
- **`options`** 可选对象:
|
2020-04-08 23:18:06 +08:00
|
|
|
|
- **`type`** —— `Blob` 类型,通常是 MIME 类型,例如 `image/png`,
|
|
|
|
|
|
- **`endings`** —— 是否转换换行符,使 `Blob` 对应于当前操作系统的换行符(`\r\n` 或 `\n`)。默认为 `"transparent"`(啥也不做),不过也可以是 `"native"`(转换)。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2019-11-08 22:53:33 +08:00
|
|
|
|
例如:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```js
|
2020-04-08 23:18:06 +08:00
|
|
|
|
// 从字符串创建 Blob
|
2019-06-11 21:33:09 +08:00
|
|
|
|
let blob = new Blob(["<html>…</html>"], {type: 'text/html'});
|
2020-04-08 23:18:06 +08:00
|
|
|
|
// 请注意:第一个参数必须是一个数组 [...]
|
2019-06-11 21:33:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
2020-04-08 23:18:06 +08:00
|
|
|
|
// 从类型化数组(typed array)和字符串创建 Blob
|
2019-11-09 23:29:10 +08:00
|
|
|
|
let hello = new Uint8Array([72, 101, 108, 108, 111]); // 二进制格式的 "hello"
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
let blob = new Blob([hello, ' ', 'world'], {type: 'text/plain'});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
我们可以用 `slice` 方法来提取 `Blob` 片段:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
|
blob.slice([byteStart], [byteEnd], [contentType]);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
- **`byteStart`** —— 起始字节,默认为 0。
|
2022-10-30 15:22:11 +08:00
|
|
|
|
- **`byteEnd`** —— 最后一个字节(不包括,默认为最后)。
|
2020-04-08 23:18:06 +08:00
|
|
|
|
- **`contentType`** —— 新 blob 的 `type`,默认与源 blob 相同。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
参数值类似于 `array.slice`,也允许是负数。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
```smart header="`Blob` 对象是不可改变的"
|
2020-04-08 23:26:02 +08:00
|
|
|
|
我们无法直接在 `Blob` 中更改数据,但我们可以通过 `slice` 获得 `Blob` 的多个部分,从这些部分创建新的 `Blob` 对象,将它们组成新的 `Blob`,等。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2019-11-09 23:29:10 +08:00
|
|
|
|
这种行为类似于 JavaScript 字符串:我们无法更改字符串中的字符,但可以生成一个新的改动过的字符串。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
## Blob 用作 URL
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
Blob 可以很容易用作 `<a>`、`<img>` 或其他标签的 URL,来显示它们的内容。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
多亏了 `type`,让我们也可以下载/上传 `Blob` 对象,而在网络请求中,`type` 自然地变成了 `Content-Type`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
让我们从一个简单的例子开始。通过点击链接,你可以下载一个具有动态生成的内容为 `hello world` 的 `Blob` 的文件:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```html run
|
2020-04-08 23:18:06 +08:00
|
|
|
|
<!-- download 特性(attribute)强制浏览器下载而不是导航 -->
|
2019-06-11 21:33:09 +08:00
|
|
|
|
<a download="hello.txt" href='#' id="link">Download</a>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
let blob = new Blob(["Hello, world!"], {type: 'text/plain'});
|
|
|
|
|
|
|
|
|
|
|
|
link.href = URL.createObjectURL(blob);
|
|
|
|
|
|
</script>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
我们也可以在 Javascript 中动态创建一个链接,通过 `link.click()` 模拟一个点击,然后便自动下载了。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
下面是类似的代码,此代码可以让用户无需任何 HTML 即可下载动态生成的 `Blob`(译注:也就是通过代码模拟用户点击,从而自动下载):
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```js run
|
|
|
|
|
|
let link = document.createElement('a');
|
|
|
|
|
|
link.download = 'hello.txt';
|
|
|
|
|
|
|
|
|
|
|
|
let blob = new Blob(['Hello, world!'], {type: 'text/plain'});
|
|
|
|
|
|
|
|
|
|
|
|
link.href = URL.createObjectURL(blob);
|
|
|
|
|
|
|
|
|
|
|
|
link.click();
|
|
|
|
|
|
|
|
|
|
|
|
URL.revokeObjectURL(link.href);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
`URL.createObjectURL` 取一个 `Blob`,并为其创建一个唯一的 URL,形式为 `blob:<origin>/<uuid>`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
也就是 `link.href` 的值的样子:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
blob:https://javascript.info/1e67e00e-860d-40a5-89ae-6ab0cbee6273
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
浏览器内部为每个通过 `URL.createObjectURL` 生成的 URL 存储了一个 URL -> `Blob` 映射。因此,此类 URL 很短,但可以访问 `Blob`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
生成的 URL(即其链接)仅在当前文档打开的状态下才有效。它允许引用 `<img>`、`<a>` 中的 `Blob`,以及基本上任何其他期望 URL 的对象。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
不过它有个副作用。虽然这里有 `Blob` 的映射,但 `Blob` 本身只保存在内存中的。浏览器无法释放它。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
在文档退出时(unload),该映射会被自动清除,因此 `Blob` 也相应被释放了。但是,如果应用程序寿命很长,那这个释放就不会很快发生。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
**因此,如果我们创建一个 URL,那么即使我们不再需要该 `Blob` 了,它也会被挂在内存中。**
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
`URL.revokeObjectURL(url)` 从内部映射中移除引用,因此允许 `Blob` 被删除(如果没有其他引用的话),并释放内存。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
在上面最后一个示例中,我们打算仅使用一次 `Blob`,来进行即时下载,因此我们立即调用 `URL.revokeObjectURL(link.href)`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
而在前一个带有可点击的 HTML 链接的示例中,我们不调用 `URL.revokeObjectURL(link.href)`,因为那样会使 `Blob` URL 无效。在调用该方法后,由于映射被删除了,因此该 URL 也就不再起作用了。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2019-11-09 23:29:10 +08:00
|
|
|
|
## Blob 转换为 base64
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
`URL.createObjectURL` 的一个替代方法是,将 `Blob` 转换为 base64-编码的字符串。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
这种编码将二进制数据表示为一个由 0 到 64 的 ASCII 码组成的字符串,非常安全且“可读“。更重要的是 —— 我们可以在 "data-url" 中使用此编码。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-11-13 22:36:05 +08:00
|
|
|
|
["data-url"](mdn:/http/Data_URIs) 的形式为 `data:[<mediatype>][;base64],<data>`。我们可以在任何地方使用这种 url,和使用“常规” url 一样。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
例如,这是一个笑脸:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
|
<img src="data:image/png;base64,R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMlWLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7">
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
浏览器将解码该字符串,并显示图像:<img src="data:image/png;base64,R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMlWLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7">
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
我们使用内建的 `FileReader` 对象来将 `Blob` 转换为 base64。它可以将 `Blob` 中的数据读取为多种格式。在[下一章](info:file) 我们将更深入地介绍它。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
下面是下载 `Blob` 的示例,这次是通过 base-64:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```js run
|
|
|
|
|
|
let link = document.createElement('a');
|
|
|
|
|
|
link.download = 'hello.txt';
|
|
|
|
|
|
|
|
|
|
|
|
let blob = new Blob(['Hello, world!'], {type: 'text/plain'});
|
|
|
|
|
|
|
|
|
|
|
|
*!*
|
|
|
|
|
|
let reader = new FileReader();
|
2020-04-08 23:18:06 +08:00
|
|
|
|
reader.readAsDataURL(blob); // 将 Blob 转换为 base64 并调用 onload
|
2019-06-11 21:33:09 +08:00
|
|
|
|
*/!*
|
|
|
|
|
|
|
|
|
|
|
|
reader.onload = function() {
|
|
|
|
|
|
link.href = reader.result; // data url
|
|
|
|
|
|
link.click();
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
这两种从 `Blob` 创建 URL 的方法都可以用。但通常 `URL.createObjectURL(blob)` 更简单快捷。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
```compare title-plus="URL.createObjectURL(blob)" title-minus="Blob 转换为 data url"
|
|
|
|
|
|
+ 如果介意内存,我们需要撤销(revoke)它们
|
|
|
|
|
|
+ 直接访问 `Blob`,无需“编码/解码”
|
|
|
|
|
|
- 无需撤销(revoke)任何操作。
|
|
|
|
|
|
- 对大的 `Blob` 进行编码时,性能和内存会有损耗。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2019-11-09 23:29:10 +08:00
|
|
|
|
## Image 转换为 blob
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
我们可以创建一个图像(image)的、图像的一部分、或者甚至创建一个页面截图的 `Blob`。这样方便将其上传至其他地方。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
图像操作是通过 `<canvas>` 元素来实现的:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-11-13 22:36:05 +08:00
|
|
|
|
1. 使用 [canvas.drawImage](mdn:/api/CanvasRenderingContext2D/drawImage) 在 canvas 上绘制图像(或图像的一部分)。
|
|
|
|
|
|
2. 调用 canvas 方法 [.toBlob(callback, format, quality)](mdn:/api/HTMLCanvasElement/toBlob) 创建一个 `Blob`,并在创建完成后使用其运行 `callback`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
在下面这个示例中,图像只是被复制了,不过我们可以在创建 blob 之前,从中裁剪图像,或者在 canvas 上对其进行转换:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```js run
|
2019-11-09 23:29:10 +08:00
|
|
|
|
// 获取任何图像
|
2019-06-11 21:33:09 +08:00
|
|
|
|
let img = document.querySelector('img');
|
|
|
|
|
|
|
2019-11-09 23:29:10 +08:00
|
|
|
|
// 生成同尺寸的 <canvas>
|
2019-06-11 21:33:09 +08:00
|
|
|
|
let canvas = document.createElement('canvas');
|
|
|
|
|
|
canvas.width = img.clientWidth;
|
|
|
|
|
|
canvas.height = img.clientHeight;
|
|
|
|
|
|
|
|
|
|
|
|
let context = canvas.getContext('2d');
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
// 向其中复制图像(此方法允许剪裁图像)
|
2019-06-11 21:33:09 +08:00
|
|
|
|
context.drawImage(img, 0, 0);
|
2020-04-08 23:18:06 +08:00
|
|
|
|
// 我们 context.rotate(),并在 canvas 上做很多其他事情
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2019-11-09 23:29:10 +08:00
|
|
|
|
// toBlob 是异步操作,结束后会调用 callback
|
2019-06-11 21:33:09 +08:00
|
|
|
|
canvas.toBlob(function(blob) {
|
2020-04-08 23:18:06 +08:00
|
|
|
|
// blob 创建完成,下载它
|
2019-06-11 21:33:09 +08:00
|
|
|
|
let link = document.createElement('a');
|
|
|
|
|
|
link.download = 'example.png';
|
|
|
|
|
|
|
|
|
|
|
|
link.href = URL.createObjectURL(blob);
|
|
|
|
|
|
link.click();
|
|
|
|
|
|
|
2020-06-04 20:03:41 +08:00
|
|
|
|
// 删除内部 blob 引用,这样浏览器可以从内存中将其清除
|
2019-06-11 21:33:09 +08:00
|
|
|
|
URL.revokeObjectURL(link.href);
|
|
|
|
|
|
}, 'image/png');
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
如果我们更喜欢 `async/await` 而不是 callback:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
```js
|
|
|
|
|
|
let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
对于页面截屏,我们可以使用诸如 <https://github.com/niklasvh/html2canvas> 之类的库。它所做的只是扫一遍浏览器页面,并将其绘制在 `<canvas>` 上。然后,我们就可以像上面一样获取一个它的 `Blob`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2022-04-20 00:37:54 +08:00
|
|
|
|
## Blob 转换为 ArrayBuffer
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2022-04-20 00:37:54 +08:00
|
|
|
|
`Blob` 构造器允许从几乎任何东西创建 blob,包括任何 `BufferSource`。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2022-05-02 04:29:16 +08:00
|
|
|
|
但是,如果我们需要执行低级别的处理时,我们可以从 `blob.arrayBuffer()` 中获取最低级别的 `ArrayBuffer`:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
|
|
|
|
|
```js
|
2023-03-28 18:50:44 +08:00
|
|
|
|
// 从 blob 获取 arrayBuffer
|
2022-05-02 04:29:16 +08:00
|
|
|
|
const bufferPromise = await blob.arrayBuffer();
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2022-05-02 04:29:16 +08:00
|
|
|
|
// 或
|
|
|
|
|
|
blob.arrayBuffer().then(buffer => /* 处理 ArrayBuffer */);
|
2019-06-11 21:33:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2022-04-20 00:37:54 +08:00
|
|
|
|
## Blob 转换为 Stream
|
2022-02-12 20:45:57 +08:00
|
|
|
|
|
|
|
|
|
|
当我们读取和写入超过 `2 GB` 的 blob 时,将其转换为 `arrayBuffer` 的使用对我们来说会更加占用内存。这种情况下,我们可以直接将 blob 转换为 stream 进行处理。
|
|
|
|
|
|
|
|
|
|
|
|
stream 是一种特殊的对象,我们可以从它那里逐部分地读取(或写入)。这块的知识点不在本文的范围之内,但这里有一个例子,你可以在 <https://developer.mozilla.org/en-US/docs/Web/API/Streams_API> 了解更多相关内容。对于适合逐段处理的数据,使用 stream 是很方便的。
|
|
|
|
|
|
|
|
|
|
|
|
`Blob` 接口里的 `stream()` 方法返回一个 `ReadableStream`,在被读取时可以返回 `Blob` 中包含的数据。
|
|
|
|
|
|
|
|
|
|
|
|
如下所示:
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
|
// 从 blob 获取可读流(readableStream)
|
|
|
|
|
|
const readableStream = blob.stream();
|
|
|
|
|
|
const stream = readableStream.getReader();
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
2022-07-13 17:42:26 +08:00
|
|
|
|
// 对于每次迭代:value 是下一个 blob 数据片段
|
|
|
|
|
|
let { done, value } = await stream.read();
|
2022-02-12 20:45:57 +08:00
|
|
|
|
if (done) {
|
|
|
|
|
|
// 读取完毕,stream 里已经没有数据了
|
|
|
|
|
|
console.log('all blob processed.');
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 对刚从 blob 中读取的数据片段做一些处理
|
2022-07-13 17:42:26 +08:00
|
|
|
|
console.log(value);
|
2022-02-12 20:45:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2019-11-09 23:29:10 +08:00
|
|
|
|
## 总结
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2022-02-12 20:45:57 +08:00
|
|
|
|
`arrayBuffer`,`Uint8Array` 及其他 `BufferSource` 是“二进制数据”,而 [Blob](https://www.w3.org/TR/FileAPI/#dfn-Blob) 则表示“具有类型的二进制数据”。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
这样可以方便 `Blob` 用于在浏览器中非常常见的上传/下载操作。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-06-04 20:03:41 +08:00
|
|
|
|
[XMLHttpRequest](info:xmlhttprequest),[fetch](info:fetch) 等进行 Web 请求的方法可以自然地使用 `Blob`,也可以使用其他类型的二进制数据。
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
我们可以轻松地在 `Blob` 和低级别的二进制数据类型之间进行转换:
|
2019-06-11 21:33:09 +08:00
|
|
|
|
|
2020-04-08 23:18:06 +08:00
|
|
|
|
- 我们可以使用 `new Blob(...)` 构造函数从一个类型化数组(typed array)创建 `Blob`。
|
2022-10-30 15:22:11 +08:00
|
|
|
|
- 我们可以使用 `blob.arrayBuffer()` 从 `Blob` 中取回 `arrayBuffer`,然后在其上创建一个视图(view),用于低级别的二进制处理。
|
2022-02-12 20:45:57 +08:00
|
|
|
|
|
|
|
|
|
|
当我们需要处理大型 blob 时,将其转换为 `stream` 非常有用。你可以轻松地从 blob 创建 `ReadableStream`。`Blob` 接口的 `stream()` 方法返回一个 `ReadableStream`,其在被读取时返回 blob 中包含的数据。
|