Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
539 views
in Technique[技术] by (71.8m points)

servlets - Should I set response.setContentLength() header?

What happen if I do not specify the Content-Length header when I send a HttpServletResponse containing a zip file?

I did some tests and it seems that the header is set by default with the correct file length. Can I be sure that this always happens. When I can found some documentation about?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If the actual response content length fits entirely in the response buffer, which is usually 2KB (it depends on server make/version/config), then the content length header will be set. However, if the actual response content length is larger than the response buffer, so that it would be flushed sooner than the end of response content is reached, then the servlet will send the response with chunked encoding and ignore any attempts to set the content length header.

This is mentioned in among others the javadoc of HttpServlet#doGet() which is cited below:

...

Where possible, set the Content-Length header (with the ServletResponse.setContentLength(int) method), to allow the servlet container to use a persistent connection to return its response to the client, improving performance. The content length is automatically set if the entire response fits inside the response buffer.

When using HTTP 1.1 chunked encoding (which means that the response has a Transfer-Encoding header), do not set the Content-Length header.

...

With "normal" encoding, the data is sent as one continuous block.

actualContent

With chunked encoding, the data is sent in chunks which look like this

part1LengthInHexadecimal
actualPart1Content

part2LengthInHexadecimal
actualPart2Content

part3LengthInHexadecimal
actualPart3Content

0

The part length in hexadecimal indicates the client how large the next chunk of data is (so that it won't "accidently" parse the next chunk as part of current chunk). Finally, the client glues the parts together. This is by the way also the default behavior when Gzip is used on the response, for the obvious reason that the final content length is unknown beforehand.

See also the example in wikipedia.

Note that when omitting the content length on a file download, then the user experience will be that the file download progress is unknown. I.e. the enduser won't see any indication of the file size and remaining bytes/time. If this user experience is important to you, then you should really set the content length beforehand. You can do this by first writing to an in-memory buffer (e.g. new ByteArrayOuputStream(bytes) or a temporary file (e.g. Files#createTempFile(), so you can get the content length by bytes.length or file.length(), and then finally write that temporary buffer/file to the response.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...