Please enable Javascript to view the contents

前端生成可下载文件详解

 ·  ☕ 4 分钟

文章内容

  • 原理
    • Blob对象
    • MIME类型
    • 构建下载链接
  • 生成文件示例
    • 生成txt
    • 生成html
    • 生成css
    • 生成json
    • 生成csv/excel
    • 生成图
    • 生成pdf

一般而言,文件下载需要两个条件:

  1. 文件
  2. 文件地址(一个指向文件的链接)

这个资源文件可能放在服务器上的静态文件,也可能是服务器动态生成的,当然,也可以由前端生成。以下为前端生成可下载文件的技术细节。

构建文件 Blob 对象

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取。

Blob 由一个可选的字符串 type(通常是 MIME 类型)和 blobParts 组成 —— 一系列其他 Blob 对象,字符串和 BufferSource。

构造函数的语法为:

new Blob(blobParts, options);
  • blobParts 是 Blob/BufferSource/String 类型的值的数组。
  • options 可选对象:
    • type —— Blob 类型,通常是 MIME 类型,例如 image/png
    • endings —— 是否转换换行符,使 Blob 对应于当前操作系统的换行符(\r\n 或 \n)。默认为 "transparent"(啥也不做),不过也可以是 "native"(转换)。

一般只用到options的type类型:

const file = new Blob([blobData], { type: filetype });

MIME 类型

媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 )是一种标准,用来表示文档、文件或字节流的性质和格式。当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

其通用结构为:

type/subtype

常见的类型有:

两种主要的 MIME 类型在默认类型中扮演了重要的角色:

  • text/plain 表示文本文件的默认值。一个文本文件应当是人类可读的,并且不包含二进制数据。
  • application/octet-stream 表示所有其他情况的默认值。一种未知的文件类型应当使用此类型。浏览器在处理这些文件时会特别小心, 试图防止、避免用户的危险行为.

构建下载链接

我们可以在 Javascript 中动态创建一个链接,通过 link.click() 模拟一个点击,然后便自动下载了。

1 URL.createObjectURL  创建资源地址指向

URL.createObjectURL 取一个 Blob,并为其创建一个唯一的 URL,形式为 blob:<origin>/<uuid>

浏览器内部为每个通过 URL.createObjectURL 生成的 URL 存储了一个 URL → Blob 映射。因此,此类 URL 很短,但可以访问 Blob

生成的 URL(即其链接)仅在当前文档打开的状态下才有效。它允许引用 <img><a> 中的 Blob,以及基本上任何其他期望 URL 的对象。

2 URL.revokeObjectURL 回收资源

不过它有个副作用。虽然这里有 Blob 的映射,但 Blob 本身只保存在内存中的。浏览器无法释放它。

在文档退出时(unload),该映射会被自动清除,因此 Blob 也相应被释放了。但是,如果应用程序寿命很长,那这个释放就不会很快发生。

因此,如果我们创建一个 URL,那么即使我们不再需要该 Blob 了,它也会被挂在内存中。

URL.revokeObjectURL(url) 从内部映射中移除引用,因此允许 Blob 被删除(如果没有其他引用的话),并释放内存。

在上面最后一个示例中,我们打算仅使用一次 Blob,来进行即时下载,因此我们立即调用 URL.revokeObjectURL(link.href)

而在前一个带有可点击的 HTML 链接的示例中,我们不调用 URL.revokeObjectURL(link.href),因为那样会使 Blob URL 无效。在调用该方法后,由于映射被删除了,因此该 URL 也就不再起作用了。

3 download 特性

download特性(attribute)强制浏览器下载而不是导航。


生成文件示例

生成.txt

生成.html

生成.css文件

生成.json文件

生成.csv文件

CSV是用UTF-8编码的,而EXCEL是ANSI编码,解决方法是在csv字符串前加上 \ufeff BOM 头。

生成图片

图像操作是通过 <canvas> 元素来实现的:

  1. 使用 canvas.drawImage 在 canvas 上绘制图像(或图像的一部分)。
  2. 调用 canvas 方法 .toBlob(callback, format, quality) 创建一个 Blob,并在创建完成后使用其运行 callback

这里推荐一个很好的工具,可以很方便将网页转换成图片。

html2canvas – Screenshots with JavaScript

html2canvas.js是一个将html dom转化成图片的 js 类库。

我用这个类库写个一个代码截图工具:

so easy…自制代码截图工具 – 码中人

生成PDF文件

跟图片一样,js生成PDF文件也是基于Canvas。推荐两个基于html2canvas的类库。

以jsPDF为例:

jsPDF生成的pdf中文字会乱码,可能是因为字体的原因。

(更多文件类型,进一步补充…)

参考资料

分享

码中人
作者
码中人
Web Developer