用浏览器访问一个指向 PDF 文件的链接,具体表现出来的行为会有所区别,最主要的区别就是在浏览器中打开(记作预览)或触发下载(记作下载)。
这些行为与请求响应结果中的 Content-Type
以及 Content-Disposition
这两个 header 有关。
对 Content-Type
取 application/pdf
、application/octet-stream
以及 application/custom-unknown
和无 Content-Disposition
、取 inline
以及 attachment
来做组合实验,得到结果如下:
header | Chrome | Firefox | Safari |
---|---|---|---|
Content-Type: application/pdf | 预览 | 预览 | 预览 |
Content-Type: application/pdf Content-Disposition: inline |
预览 | 预览 | 预览 |
Content-Type: application/pdf Content-Disposition: attachment |
下载 | 下载 | 下载 |
Content-Type: application/octet-stream | 下载 | 下载 | 下载 |
Content-Type: application/octet-stream Content-Disposition: inline |
下载 | 下载 | 下载 |
Content-Type: application/octet-stream Content-Disposition: attachment |
下载 | 下载 | 下载 |
Content-Type: application/custom-unknown | 下载 | 下载 | 下载 |
Content-Type: application/custom-unknown Content-Disposition: inline |
下载 | 下载 | 下载 |
Content-Type: application/custom-unknown Content-Disposition: attachment |
下载 | 下载 | 下载 |
Content-Type
是 application/octet-stream
表示浏览器应当把这个文件作为二进制数据来对待。但实际上浏览器可能会自己根据 Content-Disposition
甚至文件内容来做些文件格式探测,从而使用浏览器内置的功能或插件功能来处理。上面用的 application/custom-unknown
就是特意设计一个不是通用的 type 来避免已有场景。
下载时,如果没通过 Content-Disposition
指定文件名(如 Content-Disposition:inline;filename=attach.pdf
),那么下载后的文件的名称通过 url 来获取,如 /download.php
得到的是 download.php
。
Firefox 在触发下载时,如果 Content-Disposition
是 inline
,那么会静默下载,而不会像 attachment
或无该 header 时那样弹出浏览器的保存弹框。
Safari 下载后,如果是 pdf 文件(通过 Content-Type
、Content-Disposition
或其它方式识别出来),那么会自动打开该文件。
此处使用 pdf 来作为示例,对于其它类型的文件,浏览器和系统的规则推测应类似。
- 操作系统:macOS Mojave 10.14.2
- Chrome: 72.0.3626.121(正式版本) (64 位)
- Firefox: 65.0.1 (64 位)
- Safari: 12.0.2 (14606.3.4)