Content-Disposition

Content-Disposition

当我访问某些 PDF 文件地址时,Chrome 会下载 PDF,而不是使用其内置 PDF 查看器打开它。然后页面一片空白。

我的 Chrome 设置没有问题:我尝试其他 PDF 文件的地址,Chrome 的行为符合预期(我已将其设置为使用 Chrome 的内置 PDF 查看器)。但每次我尝试同一个有问题的地址时,Chrome 都会下载 PDF,然后显示空白页。

我正在使用 Windows 10 和 Chrome Version 63.0.3239.84 (Official Build) (64-bit)

我这次具体有问题的 URL 是这里(谷歌搜索结果)。

答案1

基本上,这种情况发生是因为网站告诉浏览器这样做。有时,这是因为网站开发人员决定他们想要这种行为,例如在文件共享网站上很常见。其他时候,这是因为这是他们使用的任何软件(例如论坛或博客软件)的默认选项。有时是因为网站开发人员不知道他们在做什么。


Content-Disposition

这通常是因为该网站发送了Content-Disposition响应中的标头。具体来说,它可以发送inlineattachment

inline如果没有另行指定则是默认值,这意味着如果浏览器能够打开文件,它将在浏览器窗口内打开该文件。

attachment意味着始终下载文件,从不尝试在浏览器中打开它。


如果你打开浏览器的开发人员工具,你会看到特定链接发送以下响应标头:

Content-Disposition: attachment; filename="Schubert-Sonata-21-B-flat.pdf"
Content-Type: application/pdf

这告诉浏览器总是下载( attachment) 文件,并为其指定默认文件名,Schubert-Sonata-21-B-flat.pdf而不是从 URL 推断。此外,它确实(正确地)告诉浏览器它是一个application/pdf文件 - 但由于它是一个文件,attachment浏览器仍将默认下载。


内联处理细节

当 aContent-Disposition为内联(或未指定)时,浏览器将尝试在默认的嵌入式查看器中打开文件。这仅在浏览器知道文件类型时才有效,浏览器知道如何打开该类型。

类型检测

服务器可以使用Content-Type标题。例如,最常见的内联类型是text/htmlapplication/javascripttext/css,它们构成了现代网站的三大部分。您还可以使用更深奥的类型,例如application/pdf

另一种可能是服务器指定Content-Typeapplication/octet-stream。这是最通用的类​​型,它告诉浏览器该文件只是任意数据 - 此时浏览器唯一能做的就是下载它(理论上 - 我们将会讲到这一点)。

当服务器未指定 a 时Content-Type(有时即使指定了),浏览器可以执行所谓的嗅探通过阅读文件并寻找模式来尝试猜测类型。

类型处理

收到具有或未指定属性的文件后inline,浏览器需要尝试在浏览器中打开它(如果可能)。为此,它会查看文件类型,如果识别出该类型,则会尝试打开它。大多数浏览器都会text/在简单的文本查看器中打开任何类型,尝试将其呈现text/html为网页,可能application/json在特殊的语法高亮查看器中打开, ETC..

该类型application/octet-stream是经过特殊处理的。由于它被认为是最通用的类​​型,表示任意字节流,因此不应该有任何处理程序可以应用于此“类型”的所有文件。例如,在 Firefox 中,这表现为无法设置默认处理程序为了application/octet-stream

一些网站也使用非标准类型。我见过application/force-download使用 - 最终导致下载,因为浏览器无法识别或不知道如何处理该类型,但无法享受特殊处理application/octet-stream


历史课

要了解 PDF 的处理方式,我们可以深入研究一下网络历史。过去,浏览器根本不知道 PDF 是什么。所以它们无法打开它。但早在内置 PDF 查看器出现之前,我们就发现 PDF 可以在浏览器中打开,那么它是如何工作的呢?

以前,扩展浏览器功能比现在使用有限的扩展/插件要容易得多。这些扩展/插件通常被称为插件在 Internet Explorer 中,它们是 ActiveX 控件;在 Mozilla Firefox 和后来的 Google Chrome 中,它们是 NPAPI 插件。这些插件能够执行任何其他程序可以执行的所有操作,并且还可以将自己注册为特定文件类型的处理程序,否则浏览器可能无法识别这些文件类型。(顺便说一句,后来发现这是一个巨大的安全风险,对这些强大插件的支持逐渐被取消……)

在插件时代,您可以安装 Adob​​e Acrobat Reader,然后安装 ActiveX 或 NPAPI 插件,该插件会注册application/pdfMIME 类型并告诉浏览器使用该插件以内联方式打开这些类型。

当然,在这些插件引发了一系列安全和性能问题之后,各大浏览器供应商决定整合自己的 PDF 查看器,同时逐步停止对大多数插件的支持。我们唯一仍能看到的是 Adob​​e Shockwave Flash,它可以处理application/x-shockwave-flash.

实际上仍有一些剩余的控件,例如在 Firefox 中该Preview in Firefox选项仍然存在:

选项的屏幕截图

过去,这允许在注册该类型的多个插件之间进行选择。例如,Flash 的注册类型列表:

注册类型的屏幕截图

那时 HTML5 还没有提供许多媒体支持。不仅仅是 PDF,您的浏览器不知道如何处理 MP4 容器或 H.264 视频,不知道如何播放 MP3 文件等等。您会看到 VLC 或 Windows Media Player 等媒体播放器提供的插件,或者网站会嵌入内置于 Flash 中的媒体播放器。

答案2

我找到了一个解释。根据我找到的答案,如果 MIME 内容类型设置为application/pdf“不正确或通用的 MIME 类型”, Chrome 似乎就会下载 PDF。application/octet-stream

此外, “大多数 Web 服务器使用默认 MIME 类型发送未知类型的资源application/octet-stream。出于安全原因,大多数浏览器不允许为此类资源设置自定义默认操作,从而迫使用户将其存储到磁盘才能使用它。”

答案3

这是由于HTTPContent-Disposition标头指定该文件是依恋。这将指示浏览器下载文件,而不是直接打开它。

有一个 Chrome 插件可以覆盖此行为。下图来自 Firefox 开发者工具:

Firefox 开发工具中显示的 HTTP 请求

相关内容