浏览器下载 PDF 文件

用浏览器访问一个指向 PDF 文件的链接,具体表现出来的行为会有所区别,最主要的区别就是在浏览器中打开(记作预览)或触发下载(记作下载)。

这些行为与请求响应结果中的 Content-Type 以及 Content-Disposition 这两个 header 有关。

Content-Typeapplication/pdfapplication/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-Typeapplication/octet-stream 表示浏览器应当把这个文件作为二进制数据来对待。但实际上浏览器可能会自己根据 Content-Disposition 甚至文件内容来做些文件格式探测,从而使用浏览器内置的功能或插件功能来处理。上面用的 application/custom-unknown 就是特意设计一个不是通用的 type 来避免已有场景。

下载时,如果没通过 Content-Disposition 指定文件名(如 Content-Disposition:inline;filename=attach.pdf),那么下载后的文件的名称通过 url 来获取,如 /download.php 得到的是 download.php

Firefox 在触发下载时,如果 Content-Dispositioninline,那么会静默下载,而不会像 attachment 或无该 header 时那样弹出浏览器的保存弹框。

Safari 下载后,如果是 pdf 文件(通过 Content-TypeContent-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)

参考