最近遇到一个需求,需要将页面中的配置信息下载下来供用户方便使用,以前这个场景的需求有时候会放到后端处理,然后给返回一个下载链接。其实并不需要这么麻烦,这样既增大了服务器的负载,也让用户产生了没有必要的网络请求,现在前端也是可以直接通过Blob对象进行前端文件下载了,下面简单记录下相关实现。

Blob对象介绍

Blob对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 Blob 的功能并将其扩展使其支持用户系统上的文件。 语法:

const aBlob = new Blob(array, options);
1

参数说明:

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

代码示例:

const obj = {hello: 'world'};
const blob = new Blob([JSON.stringify(obj, null, 2)], {type : 'application/json'});
1
2

URL.createObjectURL() 与 URL.revokeObjectURL()介绍

URL.createObjectURL()静态方法会创建一个DOMString,其中包含一个表示参数中给出的对象的URL。这个URL的生命周期和创建它的窗口中的document绑定。这个新的URL对象表示指定的File对象或Blob对象。相当于这个方法创建了一个传入对象的内存引用地址

createObjectURL语法

objectURL = URL.createObjectURL(object);
1

参数说明:

  • object是用于创建URL的File对象、Blob对象或者MediaSource对象。​ 返回值
  • 一个可以引用到指定对象的DOMString

URL.revokeObjectURL()静态方法用来释放一个之前已经存在的、通过调用URL.createObjectURL()创建的URL对象。当你结束使用某个URL对象之后,应该通过调用这个方法来让浏览器知道不用在内存中继续保留对这个文件的引用了。

可以在sourceopen被处理之后的任何时候调用revokeObjectURL()。这是因为createObjectURL()仅仅意味着将一个媒体元素的src属性关联到一个 MediaSource对象上去。调用revokeObjectURL()使这个潜在的对象回到原来的地方,允许平台在合适的时机进行垃圾收集。

revokeObjectURL语法

window.URL.revokeObjectURL(objectURL); 参数说明:

  • objectURL 是一个 DOMString,表示通过调用 URL.createObjectURL() 方法产生的 URL 对象。

内存管理

在每次调用createObjectURL()方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。

应用

比如在某后台管理中希望将用户的几个配置信息导入到一个json文件当中供用户下载下来。

const config = {
  name: 'lisi',
  password: '111',
  ak: 'XXXXXXXXXX',
  sk: 'XXXXXXXXXX'
};

const blobContent = new Blob(
  [JSON.stringify(config, null, 2)],
  {type : 'application/json'}
);

const blobUrl = window.URL.createObjectURL(blobContent);

downloadFileByBlob(blobUrl, 'config.json')

function downloadFileByBlob(blobUrl, filename) {
  const eleLink = document.createElement('a');
  // a标签的download属性指示浏览器下载URL而不是导航到它,因此将提示用户将其保存为本地文件。如果属性有一个值,那么此值将在下载保存过程中作为预填充的文件名(如果用户需要,仍然可以更改文件名)。
  eleLink.download = filename; // 指定下载文件名称
  eleLink.href = blobUrl;
  // 触发点击
  eleLink.click();
  window.URL.revokeObjectURL(blobContent);
  // eleLink.style.display = 'none';
  // document.body.appendChild(eleLink);
  // 然后移除
  // document.body.removeChild(eleLink);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

执行上述代码,我们可以得到一个config.json的文件,可以看到,其实很简单就实现了这个场景需求,当然这里是下载的json文件,下载其他的文件也是一样的道理,只是需要得到相应文件的blob数据,再结合相应的MIME类型即可。

兼容性方面目前主流浏览器都已支持,ie10以及以上也支持。 另外,Blob结合URL.createObjectURL()与URL.revokeObjectURL()还可以用在预览图片、预览PDF、视频链接防盗等多种场景中。