目录

前端下载文件的几种方式

前端下载文件的几种方式

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.downloadwindow.download 是假想)。

3. location.href

这种方式和 window.open(url) 是一样的,代码如下:

location.href = '/test.xlsx'

这种方式拥有 window.open 的所有缺陷,所以不推荐使用。

4. location.?其他属性

这里的其他指代的都是能跳转页面的属性,比如 location.assignlocation.replacelocation.reload 等,这些属性都是可以实现文件下载的,代码如下:

location.assign('http://www.baidu.com')
location.replace('http://www.baidu.com')
location.reload('http://www.baidu.com')

这里的 location.reload 是有点特殊的,它的作用是重新加载当前页面,但是它也可以接受一个参数,这个参数就是要跳转的页面,所以也可以实现文件下载。

5. XMLHttpRequest

这种方式就是我们常说的 ajax 下载,包括 axiosfetch 等都是相同的,代码如下:

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)