前端下载文件的几种方式
前端下载文件的几种方式
1. a 标签
通过
a
标签的
download
属性来实现文件下载,这种方式是最简单的,也是我们比较常用的方式,示例代码:
<a href="http://www.baidu.com" download="baidu.html">下载</a>
就上面的这个示例,我们点击下载,发现是跳转到了百度的首页,并没有真的下载文件。
因为
a
标签下载只能下载同源的文件,如果是跨域的文件,这里包括图片、音视频等媒体文件,都是预览,也无法下载。
并且通过
download
属性,可以实现对下载的文件进行重命名。
<a href="/test.xlsx" download="anna.xlsx">下载文件</a>
上面的代码是直接通过书写
a
标签来实现文件下载,我们也可以通过
js
来实现,代码如下:
const a = document.createElement('a')
a.href = '/test.xlsx'
a.download = 'anna.xlsx'
a.click()
这里的重点是
a
标签的
download
属性,这个属性是
HTML5
新增的。
它的作用是指定下载的文件名,如果不指定,那么下载的文件名就会根据请求内容的
Content-Disposition
来确定,如果没有
Content-Disposition
,那么就会使用请求的
URL
的最后一部分作为文件名。
2. window.open
上面使用
a
标签的案例也可以通过
window.open
来实现,效果是一样的,代码如下:
window.open('/test.xlsx', '_blank')
这里的
_blank
是指定打开的方式,如果不指定,那么就会在当前页面打开,这里指定
_blank
,就是在新的页面打开。
同样
a
标签的
download
属性也是可以使用的,代码如下:
window.open('/test.xlsx', '_blank', 'download=baidu.html')
这种方式是有缺陷的,对比于
a
标签,这种方式不能下载
.html
、
.htm
、
.xml
、
.xhtml
等文件,因为这些文件会被当成
html
文件来处理,所以会直接在当前页面打开,并且没有重命名的方式。
同样也不能下载跨域的文件,毕竟是
window.open
,不是
window.download
(
window.download
是假想)。
3. location.href
这种方式和
window.open(url)
是一样的,代码如下:
location.href = '/test.xlsx'
这种方式拥有
window.open
的所有缺陷,所以不推荐使用。
4. location.?其他属性
这里的其他指代的都是能跳转页面的属性,比如
location.assign
、
location.replace
、
location.reload
等,这些属性都是可以实现文件下载的,代码如下:
location.assign('http://www.baidu.com')
location.replace('http://www.baidu.com')
location.reload('http://www.baidu.com')
这里的
location.reload
是有点特殊的,它的作用是重新加载当前页面,但是它也可以接受一个参数,这个参数就是要跳转的页面,所以也可以实现文件下载。
5. XMLHttpRequest
这种方式就是我们常说的
ajax
下载,包括
axios
、
fetch
等都是相同的,代码如下:
const xhr = new XMLHttpRequest()
xhr.open('GET', '/test.xlsx')
xhr.send()
xhr.onload = function () {
const blob = new Blob([xhr.response], { type: 'text/html' })
const a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = 'anna.xlsx'
a.click()
}
// axios
axios({
url: "/test.xlsx",
method: 'GET',
responseType: 'blob',
headers: {
token: test // 可以携带 token
}
}).then(res => {
const href = URL.createObjectURL(res.data)
const a = document.createElement('a')
a.download = 'anna.xlsx'
a.href = href
a.click()
})
这里主要的逻辑是当我们的请求成功后,我们会拿到响应体的
response
,这个
response
就是我们要下载的内容,然后我们把它转换成
blob
对象,然后通过
URL.createObjectURL
来创建一个
url
,然后通过
a
标签的
download
属性来实现文件下载。
5.1 blob
blob
对象的定义:
Blob
对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成ReadableStream
来用于数据操作。
Blob
表示的不一定是JavaScript
原生格式的数据。File
接口基于Blob
,继承了blob
的功能并将其扩展以支持用户系统上的文件。
blob
对象是
html5
新增的对象,它的作用是用来存储二进制数据的,比如图片、视频、音频等,它的使用方法如下:
/**
- @param {Array} array 二进制数据
- @param {Object} options 配置项
- @param {String} options.type 文件类型,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。
- @param {String} options.endings 用于指定包含行结束符\n的字符串如何被写入。默认为transparent,表示不会修改行结束符。还可以指定为native,表示会将\n转换为\r\n。
*/
const blob = new Blob([], { type: '' })
这里主要关注的是
type
属性,默认情况下,
blob
对象是没有
type
属性的,那么这个
Blob
就是一个无类型的
Blob
,文件不会损毁,但是无法被正常识别。
5.2 URL.createObjectURL
URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的 URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的 URL 对象表示指定的 File 对象或 Blob 对象。
这个方法是用来创建一个
url
的,它的作用是把一个
blob
对象转换成一个
url
,这个
url
可以用来下载文件,也可以用来预览文件,代码如下:
const url = URL.createObjectURL(blob)
这里需要注意的是,这个
url
的生命周期和创建它的窗口中的
document
绑定,也就是说,当我们的
document
被销毁后,这个
url
就会失效,所以我们需要在合适的时机销毁它,代码如下:
URL.revokeObjectURL(url)