跳到主要内容

前端下载

对于浏览器来说,部分文件是可以预览的,如 png, jpeg, gif,一般来说,浏览器打开这些文件时,不会自动下载;只有在打开比如 zip 等不支持预览的文件时,才会自动下载。

下载的方式又分为 a 标签的 download 和响应头 content-disposition.

这里分别讨论不同场景浏览器会如何处理,以及两种下载方式的优先级。

不下载

zippng
同源下载预览
跨域下载预览

a 标签 download

需要注意的是,对于跨域的链接,a 标签 download 属性是无效的,相当于没设置这个属性!

简单用法

<a href="/path/to/filename" download="filename">点击下载</a>

JS 版本

const downloadByUrl = (url: string, filename: string) => {
if (!url) {
throw new Error('当前没有下载链接')
}

const a = document.createElement('a')
a.style.display = 'none'
a.href = url
a.download = filename
a.rel = 'noopener noreferrer'

document.body.append(a)
a.click()
document.body.removeChild(a)
}

直接将下载链接添加 a 标签 href 属性的问题在于它并不能携带更多信息,比如请求头。因此大多数时候我们会借助 blob 进行类型转换再下载

function download(imageUrl: string, filename: string) {
return fetch(imageUrl)
.then((response) => response.blob())
.then((blob) => {
const downloadUrl = URL.createObjectURL(blob)
const a = document.createElement('a')

a.href = downloadUrl
a.download = filename

document.body.appendChild(a)
a.click()
// 清理工作
document.body.removeChild(a)
URL.revokeObjectURL(downloadUrl)
})
.catch((error) => console.error('Error downloading the image:', error))
}

浏览器处理

zippng
同源下载下载
跨域下载预览

Content-Disposition

信息

MDN: 在常规的 HTTP 应答中,Content-Disposition 响应标头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地

响应示例

Content-Disposition: inline
Content-Disposition: attachment; filename="filename.jpg"

浏览器处理

zippng
同源下载下载
跨域下载下载

优先级

  • inline 的优先级和 download 怎么样?

    download > inline。可能不算优先级更高?理解成只要任意方式设置为去下载,就去下载文件!

  • download 和 attachment filename 哪个优先级更高?

    attachment

处理方式总结

zippng
不下载
同源下载预览
跨域下载预览
download
同源下载下载
跨域下载预览
content-disposition
同源下载下载
跨域下载下载