为什么无法下载状态代码为 4XX 和 5XX 的文件

Why isn't it possible to download a file for status code 4XX and 5XX

我注意到许多 http 客户端,包括 Firefox 和 Chrome 不允许下载带有 4XX 和 5XX 的 http 响应代码的文件。但是,某些客户端允许这些下载,例如 curl 和 wget(带有 --content-on-error 选项)。

Chrome 和 Firefox 都不提供很好的异常消息。 Chrome 失败并返回 ERR_INVALID_RESPONSE。 Firefox 失败并显示 File not found。如上所述,对于相同的 URL.

的 curly 和 wget 工作

我想知道在这种情况下是否有定义正确行为的规范? Chrome 和 Firefox 无法处理请求是否有充分的理由?另外,他们没有提供适当的反馈似乎很奇怪。

我认为在大多数情况下下载失败的请求没有意义,但在某些情况下它会有所帮助。一个即使在错误情况下也下载文件的好例子是,如果有一个客户端只使用某种第 3 方格式与服务器通信。客户端必须为请求下载生成的文件。如果出现错误,客户端应下载包含错误描述的文件。

例如RFC7231状态

Response messages with an error status code usually contain a payload that represents the error condition, such that it describes the error state and what next steps are suggested for resolving it.


The 4xx (Client Error) class of status code indicates that the client seems to have erred. Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents SHOULD display any included representation to the user.

这并不禁止在出现错误的情况下下载。


编辑因为第一个答案:

我不认为这种行为对用户友好,我也不认为用户友好性真的是这背后的原因。例如,向用户显示错误代码和错误消息(在 header 中提供)会更有意义。或者至少用诸如“无法下载文件,因为服务器响应错误”之类的错误消息来指示错误。可能有些服务器只能响应 XML 或任何其他随机文件格式。

最让我烦恼的是,两种浏览器都会响应不同但任意的错误,这些错误不会提示有关潜在问题的任何信息。

这可能是一个未记录的边缘案例,Chrome 和 Firefox 都只是回退到默认错误,但这似乎不太可能,特别是因为这是一个在wget.

4XX: Why would you assume a file download if your client did something wrong?

如果我们假设 API 有一个以特定文件格式回复的端点,则可以公平地假设错误消息也以该格式提供,包括提示客户端做错了什么。因此该文件可以帮助修复客户端错误。

我不知道该主题的任何规范。 行为应尽可能对用户友好。

4XX: 如果您的客户做错了什么,您为什么要假设文件下载?此外,客户端软件在错误使用(例如无效 url)和处理文件下载的情况下无法区分。

5xx: 正如你所说,大多数 api 提供错误信息,但你也可以区分下载的情况,例如提供文件的内部错误。

您可以像您提到的那样将这种行为与 wget 和 curl 一起使用,但是以编程方式使用这种 API 对用户来说既不友好也不实用。

记住以上信息,Chrome 和 firefox 只是尽量对用户友好。

我希望我能以某种方式回答你的问题或挑战它背后的想法。 :)

查看 chromium handle download and not 2xx 我们看到:

  // The response code indicates that this is an error page, but we don't
  // know how to display the content.  We follow Firefox here and show our
  // own error page instead of intercepting the request as a stream or a
  // download.

所以 Chrome 遵循了 Firefox,两者都与 RFC 完全一致,浏览器知道 this payload is unidentified 与错误条件相关的数据,因此将其保存为有问题的文件不是一个选项.由于正在下载,浏览器可能无法显示有效载荷,但在任何一种情况下都已指示不要这样做,因此在错误上下文中显示它不是一个安全的选择。由于这是一个错误,因此发送方也很可能将部分响应与错误代码组合在一起,这意味着有效负载内容可能是来自 2xx response/etc.[=14= 的数据的不完整或损坏的表示形式。 ]

如果你回头看看 wget,--content-on-error 是一个特定的选项,因为作为一般浏览器,它是错误的做法。使用负载类型的客户端可以在直接与服务器交互时检查错误,而 wget 仅提供选项来帮助您调试此类交互。与文本 CLI 相比,普通浏览器可帮助模拟其他客户端进行调试的功能较少,因为文本 CLI 的存在主要是为了在调试时模拟其他客户端。

I was wondering if there is a specification that defines the correct behavior in this case? Are there good reasons why the request can't be processed by Chrome and Firefox? Also, it seems strange that they don't provide proper feedback.

对此没有这样的规范,但 chromium 项目成员认为这是一个微不足道的问题,不太可能在不久的将来得到解决。他们建议应该通过发送正确的 HTTP 状态将其固定在服务器上,而不是固定在铬中。

Response from Chromium Project Member: "This issue has been Available for over a year. If it's no longer important or seems unlikely to be fixed, please consider closing it out. If it is important, please re-triage the issue."

Sorry for the inconvenience if the bug really should have been left as Available.

您可以在此处查看更多详细信息Issue 479265

表面之下发生了什么?

我进一步检查了 chromium 的源代码以查找实际发生的情况,发现对于任何非 200 状态的下载,它们只是抛出 ERR_INVALID_RESPONSE(无效的服务器响应)错误。

长话短说,您必须忍受浏览器的这种行为,它不会得到改进。

这些答案似乎都绕过了这里的基本原理:您正试图对代码中的错误给出特定于浏览器的解释。从我的角度来看,在所有相关情况下,您的代码都以某种方式失败而没有错误处理。

4xx错误?根据确定的规则,您向服务器发送了错误请求。从技术上讲,这不是浏览器的错。

5xx 错误? 您的 服务器崩溃并且没有抛出错误。在某些类型的服务器上,(Django) 500 错误将是一堆您可能不应该向用户显示的调试信息。

因此,从架构的角度来看,您的要求很奇怪;你想通过修改浏览器的响应来掩盖你搞砸了的事实,而不是修复你的代码以适当地响应。

的基础上,Chromium 似乎决定效仿 Firefox 的决定,如果响应不成功则不下载文件。

看来这个问题已经有历史了。 2005 年,AOL 网站出现问题,返回状态代码 500 并导致用户下载 .exe 文件。有一个 "fix" 只是 returns 一个 404 用于触发下载和错误响应的响应。可以找到对应的issue here.

2008 年有一个未解决的问题,抱怨这个错误并声明它会产生误导。可以找到对应的issue here.

我在 Super User 上找到了更详细的答案。

我仍然认为至少为用户提供一个选择来下载文件或至少显示一个更有意义的错误页面是正确的。另一方面,在大多数情况下,响应代码 != 2XX 的下载是无意的,并暗示服务器错误。因此,对于浏览器供应商来说,这个问题的优先级似乎很低,似乎 "not worth the trouble".