Blob 二进制数据存储在哪里

Where is Blob binary data stored?

本文关键字:在哪里 存储 数据 二进制 Blob      更新时间:2023-09-26

给定

var data = new Array(1000000);
for (var i = 0; i < data.length; i++) {
  data[i] = 1;
}
var blob = new Blob([data]);

数组的二进制数据表示形式存储在哪里?

Blob 表示一堆可以存在于任何地方的数据。文件 API 规范有意不提供任何读取 Blob 内容的同步方法。

以下是一些具体的可能性。

  1. 当您通过构造函数创建 Blob 并将其传递到内存中的数据(如Uint8Array)时,Blob 的内容至少在内存中存在一段时间。
  2. <input type="file"> 获取 Blob 时,Blob 的内容位于磁盘上,位于用户选择的文件中。该规范提到了快照,但没有实现这样做,因为它会给用户操作增加很多滞后。
  3. 从另一个客户端存储 API(如 IndexedDB 或缓存存储 API)获取 Blob 时,Blob 的内容将位于磁盘上 API 的后备存储中。
  4. 某些 API 可能会返回其数据从网络流式传输的 Blob。XMLHttpRequest 规范使这是不可能的,我认为获取规范还需要在创建 Blob 之前检索整个响应。但是,将来可能会有一个流式传输 HTTP 响应的规范。
  5. 通过 Blob 构造函数通过片段数组创建的 Blob 的内容可能分散在上述所有位置。

在 Chrome 中,我们使用多进程架构,其中浏览器进程具有所有实时 Blob 的中央注册表,并充当 Blob 内容的真实来源。在渲染器(通过 JavaScript)中创建 Blob 时,其内容将通过 IPC、共享内存或临时文件移动到浏览器进程,具体取决于 Blob 的大小。浏览器进程还可能会将内存中的 Blob 内容逐出到临时文件。之前答案中提到的500mb限制在2016年左右被取消。更多实现细节在 Chrome Blobs 子系统的自述文件中。

所有未在任何其他存储中显式表示的变量都存储在内存 (RAM) 中,并一直存在到程序结束或取消设置时(从内存中清除它)。

TLDR;在内存中

这不会完全回答您的问题。

那么,当宣布new Blob()时会发生什么?

来自官方文件API文档,

The Blob() constructor can be invoked with zero or more parameters. When the Blob() constructor is invoked, user agents must run the following Blob constructor steps:
[1] If invoked with zero parameters, return a new Blob object with its readability state set to OPENED, consisting of 0 bytes, with size set to 0, and with type set to the empty string.
[2] Otherwise, the constructor is invoked with a blobParts sequence. Let a be that sequence.
[3] Let bytes be an empty sequence of bytes.
[4] Let length be `a`s length. For 0 ≤ i < length, repeat the following steps:
    1. Let element be the ith element of a.
    2. If element is a DOMString, run the following substeps:
        Let s be the result of converting element to a sequence of Unicode characters [Unicode] using the algorithm for doing so in WebIDL.
        Encode s as UTF-8 and append the resulting bytes to bytes.
    Note:
        The algorithm from WebIDL [WebIDL] replaces unmatched surrogates in an invalid UTF-16 string with U+FFFD replacement characters. Scenarios exist when the Blob constructor may result in some data loss due to lost or scrambled character sequences.  
    3. If element is an ArrayBufferView [TypedArrays], convert it to a sequence of byteLength bytes from the underlying ArrayBuffer, starting at the byteOffset of the ArrayBufferView [TypedArrays], and append those bytes to bytes.
    4. If element is an ArrayBuffer [TypedArrays], convert it to a sequence of byteLength bytes, and append those bytes to bytes.
    5. If element is a Blob, append the bytes it represents to bytes. The type of the Blob array element is ignored.  
[5] If the type member of the optional options argument is provided and is not the empty string, run the following sub-steps:
    1. Let t be the type dictionary member. If t contains any characters outside the range U+0020 to U+007E, then set t to the empty string and return from these substeps.
    2. Convert every character in t to lowercase using the "converting a string to ASCII lowercase" algorithm.
[6] Return a Blob object with its readability state set to OPENED, referring to bytes as its associated byte sequence, with its size set to the length of bytes, and its type set to the value of t from the substeps above. 

Blob存储在内存中,就像任何其他ArrayBuffer一样。它存储在 ram 中,就像在窗口中声明的其他对象一样。

查看chrome://blob-internals,我们可以看到它是如何物理存储在公羊中的。下面是一个示例 blob。

c7828dad-dd4f-44e6-b374-9239dbe35e35
    Refcount: 1
    Status: BlobStatus::DONE: Blob built with no errors.
    Content Type: application/javascript
    Type: file
    Path: /Users/Chetan/Library/Application Support/Google/Chrome/Default/blob_storage/c7828dad-dd4f-44e6-b374-9239dbe35e35/0
    Modification Time: Monday, June 5, 2017 at 4:29:53 PM
    Offset: 4,917,846
    Length: 224,733

在打印 blob 的实际内容时,我们得到一个普通的 js 文件。

$ cat c7828dad-dd4f-44e6-b374-9239dbe35e35/0
...
html {
   font-family: sans-serif;
   /* 1 */
   -ms-text-size-adjust: 100%;
   /* 2 */
   -webkit-text-size-adjust: 100%;
   /* 2 */ }
/**
 * Remove default margin.
 */
body {
    margin: 0; }
...

Blob 存储在内存中。在浏览器 Blob 存储中。如果你创建了一个 blob 对象,你可以在 Firefox 内存分析器(about:memory)上检查它。火狐输出的示例,在这里我们可以看到选定的文件。Blob 和文件之间存在差异。Blob 存储在内存中,文件存储在文件系统中。

651.04 MB (100.0%) -- explicit
├──430.49 MB (66.12%) -- dom
│  ├──428.99 MB (65.89%) -- memory-file-data
│  │  ├──428.93 MB (65.88%) -- large
│  │  │  ├────4.00 MB (00.61%) ── file(length=2111596, sha1=b95ccd8d05cb3e7a4038ec5db1a96d206639b740)
│  │  │  ├────4.00 MB (00.61%) ── file(length=2126739, sha1=15edd5bb2a17675ae3f314538b2ec16f647e75d7)

谷歌浏览器有一个错误。Chrome 有 blob 限制。创建的总 blob 量超过 500MB 时。浏览器将停止创建 Blob,因为 Blob 存储已达到 500MB 的限制。避免这种情况的唯一方法是将 blob 写入 IndexDb 并从 IndexDb 中删除。将 blob 写入 indexDB 时,blob 对象将自动保存到文件系统(blob 将转换为文件)。停止使用 Blob 后,将使用垃圾回收器从内存中清除 Blob,或使 Blob = null。但是 GC 会在一段时间后删除 blob,而不是立即删除。