文件下载的潜规则:a标签下载or在线预览
2023-10-12 06:41:41
Internet Explorer的祖坟从土里拱出来后,我们发现了一个有趣的现象:在跨域 情况下,使用<a>
标签下载某些类型的文件(比如.json
、.txt
、.png
等)时,浏览器会自动切换到在线预览 模式,而不是直接下载文件。
但奇怪的是,在同源 情况下,一切又恢复了正常,<a>
标签可以乖乖地下载文件。
这到底是浏览器抽风了,还是另有玄机?今天,我们就来一探究竟。
浏览器为何要在线预览?
为了搞清楚这个问题,我们先来看看浏览器的下载机制。
当用户点击<a>
标签时,浏览器会向服务器发送一个HTTP请求,请求获取该文件。服务器收到请求后,会返回一个HTTP响应,其中包含文件的内容和一些额外的信息,比如文件的MIME类型。
浏览器根据MIME类型来判断如何处理该文件。如果MIME类型表示该文件是可下载的(比如application/octet-stream
),浏览器就会直接下载文件;如果MIME类型表示该文件是可在线预览的(比如text/plain
),浏览器就会在线预览该文件。
跨域下载的特殊性
在同源情况下,浏览器可以正确地识别文件的MIME类型,因此<a>
标签可以正常地下载文件。
但是在跨域情况下,浏览器会对文件的MIME类型进行额外的检查。如果文件的MIME类型不在浏览器的白名单 中,浏览器就会将该文件视为可在线预览的文件,并自动切换到在线预览模式。
浏览器的白名单是由浏览器厂商维护的,不同的浏览器有不同的白名单。比如,Chrome浏览器的白名单中包含了application/octet-stream
、application/pdf
、application/zip
等MIME类型,但并不包含text/plain
、.json
等MIME类型。
如何强制下载文件?
既然知道了浏览器在线预览的机制,我们就可以想办法强制浏览器下载文件了。
最简单的方法就是在<a>
标签中添加download
属性,比如:
<a href="file.txt" download>下载文件</a>
添加了download
属性后,浏览器就会忽略文件的MIME类型,直接下载该文件。
另一种方法是使用Content-Disposition
首部字段。在服务器响应中,添加Content-Disposition: attachment; filename=file.txt
首部字段,可以强制浏览器下载该文件。
总结
在跨域情况下,浏览器会对<a>
标签下载的文件进行额外的检查。如果文件的MIME类型不在浏览器的白名单中,浏览器就会将该文件视为可在线预览的文件,并自动切换到在线预览模式。
我们可以通过添加download
属性或使用Content-Disposition
首部字段来强制浏览器下载文件。