Data协议

定义

Data URLs,即前缀为 data: 协议的URL,其允许内容创建者向文档中嵌入小文件。

Data URLs 由四个部分组成:前缀(data:)、指示数据类型的MIME类型、如果非文本则为可选的base64标记、数据本身:

data:[<mediatype>][;base64],<data>

mediatype 是个 MIME 类型的字符串,例如 "image/jpeg" 表示 JPEG 图像文件。如果被省略,则默认值为text/plain;charset=US-ASCII

如果数据是文本类型,你可以直接将文本嵌入 (根据文档类型,使用合适的实体字符或转义字符)。如果是二进制数据,你可以将数据进行base64编码之后再进行嵌入。

下面是一些示例:

  • data:,Hello%2C%20World!

    简单的 text/plain 类型数据

  • data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

    上一条示例的 base64 编码版本

  • data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E

    一个HTML文档源代码 <h1>Hello, World</h1>

  • data:text/html,<script>alert('hi');</script>

    一个会执行 JavaScript alert 的 HTML 文档。注意 script 标签必须封闭。

常见问题

语法

data URLs 的格式很简单,但很容易会忘记把逗号加在 "data" 协议名后面,在对数据进行 base64 编码时也很容易发生错误。

HTML代码格式化

一个 data URL 是一个文件中的文件,相对于文档来说这个文件可能就非常的长。因为 data URL 也是 URL,所以 data 会用空白符(换行符, 制表符, 空格)来对它进行格式化。但如果数据是经过 base64 编码的,就可能会遇到一些问题open in new window

长度限制

有些浏览器支持无限制长度的url,比如FireFox,而有些浏览器对url做了限制,比如Opera 11浏览器限制 URLs 最长为 65535 个字符,这意味着 data URLs 最长为 65529 个字符。

缺乏错误处理

MIME类型错误或者base64编码错误,都会造成data URL无法被正常解析,但却没有任何相关提示。

不支持查询字符串

一个data URL的数据字段是没有结束标记的,所以尝试在一个data URL后面添加查询字符串会导致查询字符串被当做数据字段。

File协议

File协议也叫本地文件传输协议,主要用于访问本地计算机的文件

基本格式:file:///文件路径

URL中为什么本地文件file后面跟三个斜杠, http等协议跟两个斜杠?

  • 因为URL结构是: <协议>://<主机>:<端口>/<路径>
  • 如果有主机,前面是要加 // 的,因此对于 http等这些网络地址是http://127.0.0.1:5500/bigwatermelon/index.htmlopen in new window
  • 如果是文件,文件没有主机,所以中间的部分就不要了,就变成了file:///D:/mywebproject/bigwatermelon/index.html

浏览器通过file:///访问文件和http://访问文件的区别

  • file协议只能在本地访问,file无法实现跨域,file协议对应有一个类似http的远程访问,就是ftp协议,即文件传输协议。本地搭建http服务器开放端口后他人也可以通过http访问到你电脑中的文件,但是file协议做不到。
  • http访问本地的html文件,相当于将本机作为了一台http服务器,然后通过主机访问的是你自己电脑上的本地服务器,再通过http服务器去访问你本机的文件资源。断网就打不开了。
  • file只是简单请求了本地文件,将其作为一个服务器未解析的静态文件打开,断网也可以打开。而http是在本地搭建了一个服务器再通过服务器去动态解析拿到文件。

Blob协议

Blob URL/Object URL 是一种伪协议,允许 Blob 和 File 对象用作图像,下载二进制数据链接等的 URL 源。在浏览器中,我们使用 URL.createObjectURL 方法来创建 Blob URL,该方法接收一个 Blob 对象,并为其创建一个唯一的 URL,其形式为 blob:<origin>/<uuid>,对应的示例如下:

blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f641

浏览器内部为每个通过 URL.createObjectURL 生成的 URL 存储了一个 URL → Blob 映射。因此,此类 URL 较短,但可以访问 Blob。生成的 URL 仅在当前文档打开的状态下才有效。它允许引用 <img><a> 中的 Blob,但如果你访问的 Blob URL 不再存在,则会从浏览器中收到 404 错误。

上述的 Blob URL 看似很不错,但实际上它也有副作用。虽然存储了 URL → Blob 的映射,但 Blob 本身仍驻留在内存中,浏览器无法释放它。映射在文档卸载时自动清除,因此 Blob 对象随后被释放。但是,如果应用程序寿命很长,那不会很快发生。因此,如果我们创建一个 Blob URL,即使不再需要该 Blob,它也会存在内存中。

针对这个问题,我们可以调用 URL.revokeObjectURL(url) 方法,从内部映射中删除引用,从而允许删除 Blob(如果没有其他引用),并释放内存。

const download = (fileName, blob) => {
  const link = document.createElement("a");
  link.href = URL.createObjectURL(blob);
  link.download = fileName;
  link.click();
  link.remove();
  URL.revokeObjectURL(link.href);
};

const downloadBtn = document.querySelector("#downloadBtn");
downloadBtn.addEventListener("click", (event) => {
  const fileName = "blob.txt";
  const myBlob = new Blob(["一文彻底掌握 Blob Web API"], { type: "text/plain" });
  download(fileName, myBlob);
});
上次更新:
贡献者: chenzilin