返回

文件下载的潜规则:a标签下载or在线预览

前端

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-streamapplication/pdfapplication/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首部字段来强制浏览器下载文件。