1

如果我Content-Length在发送HttpServletResponse包含 zip 文件的文件时未指定标头会怎样?

我做了一些测试,似乎默认情况下标题设置为正确的文件长度。我能确定这总是发生吗?我什么时候可以找到一些关于?

4

1 回答 1

2

如果实际响应内容长度完全适合响应缓冲区,通常为 2KB(取决于服务器的 make/version/config),则将设置内容长度标头。但是,如果实际响应内容长度大于响应缓冲区,那么它将在到达响应内容结尾之前被刷新,那么 servlet 将使用分块编码发送响应并忽略任何设置内容长度的尝试标题。

这在下面引用的 javadoc 中HttpServlet#doGet()提到:

...

在可能的情况下,设置 Content-Length 标头(使用ServletResponse.setContentLength(int)方法),以允许 servlet 容器使用持久连接将其响应返回给客户端,从而提高性能。如果整个响应都适合响应缓冲区,则会自动设置内容长度。

使用 HTTP 1.1 分块编码时(这意味着响应具有 Transfer-Encoding 标头),请勿设置 Content-Length 标头。

...

使用“正常”编码,数据作为一个连续块发送。

actualContent

使用分块编码,数据以如下所示的块发送

part1LengthInHexadecimal
actualPart1Content

part2LengthInHexadecimal
actualPart2Content

part3LengthInHexadecimal
actualPart3Content

0

十六进制的部分长度指示客户端下一个数据块有多大(这样它就不会“意外地”将下一个块解析为当前块的一部分)。最后,客户将零件粘合在一起。顺便说一句,这也是在响应中使用 Gzip 时的默认行为,原因很明显,最终内容长度事先是未知的。

另请参阅wikipedia中的示例。

请注意,当在文件下载中省略内容长度时,用户体验将是文件下载进度未知。即最终用户将看不到文件大小和剩余字节/时间的任何指示。如果这种用户体验对您很重要,那么您应该事先设置内容长度。您可以通过首先写入内存缓冲区(例如new ByteArrayOuputStream(bytes)或临时文件(例如,因此您可以通过或Files#createTempFile()获取内容长度,然后最后将该临时缓冲区/文件写入响应来做到这一点。bytes.lengthfile.length()

于 2013-01-17T17:53:52.607 回答