如果我Content-Length
在发送HttpServletResponse
包含 zip 文件的文件时未指定标头会怎样?
我做了一些测试,似乎默认情况下标题设置为正确的文件长度。我能确定这总是发生吗?我什么时候可以找到一些关于?
如果我Content-Length
在发送HttpServletResponse
包含 zip 文件的文件时未指定标头会怎样?
我做了一些测试,似乎默认情况下标题设置为正确的文件长度。我能确定这总是发生吗?我什么时候可以找到一些关于?
如果实际响应内容长度完全适合响应缓冲区,通常为 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.length
file.length()