文章内容
- 原理
- Blob对象
- MIME类型
- 构建下载链接
- 生成文件示例
- 生成txt
- 生成html
- 生成css
- 生成json
- 生成csv/excel
- 生成图
- 生成pdf
一般而言,文件下载需要两个条件:
- 文件
- 文件地址(一个指向文件的链接)
这个资源文件可能放在服务器上的静态文件,也可能是服务器动态生成的,当然,也可以由前端生成。以下为前端生成可下载文件的技术细节。
构建文件 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>
元素来实现的:
- 使用 canvas.drawImage 在 canvas 上绘制图像(或图像的一部分)。
- 调用 canvas 方法 .toBlob(callback, format, quality) 创建一个
Blob
,并在创建完成后使用其运行callback
。
这里推荐一个很好的工具,可以很方便将网页转换成图片。
html2canvas – Screenshots with JavaScript
html2canvas.js是一个将html dom转化成图片的 js 类库。
我用这个类库写个一个代码截图工具:
生成PDF文件
跟图片一样,js生成PDF文件也是基于Canvas。推荐两个基于html2canvas的类库。
- html2pdf.js | Client-side HTML-to-PDF rendering using pure JS.
- jsPDF - HTML5 PDF Generator | Parallax
以jsPDF为例:
jsPDF生成的pdf中文字会乱码,可能是因为字体的原因。
(更多文件类型,进一步补充…)