Должен ли я установить заголовок response.setContentLength()?

Что произойдет, если я не укажу заголовок Content-Length при отправке HttpServletResponse, содержащего zip-файл?

Я провел несколько тестов, и кажется, что заголовок по умолчанию имеет правильную длину файла. Могу ли я быть уверен, что это происходит всегда. Когда я смогу найти документацию о?


person Panciz    schedule 17.01.2013    source источник
comment
Вам никогда не нужно устанавливать его в сервлете.   -  person user207421    schedule 17.01.2013


Ответы (1)


Если фактическая длина содержимого ответа полностью помещается в буфер ответа, который обычно составляет 2 КБ (это зависит от производителя/версии/конфигурации сервера), то будет установлен заголовок длины содержимого. Однако, если фактическая длина содержимого ответа больше, чем буфер ответа, так что он будет очищен раньше, чем будет достигнут конец содержимого ответа, тогда сервлет отправит ответ с фрагментированное кодирование и игнорировать любые попытки установить заголовок длины содержимого.

Это упоминается, среди прочего, в javadoc HttpServlet#doGet(), приведенный ниже:

...

По возможности установите заголовок Content-Length (с ServletResponse.setContentLength(int)), чтобы позволить контейнеру сервлетов использовать постоянное соединение для возврата ответа клиенту, повышая производительность. Длина содержимого устанавливается автоматически, если весь ответ помещается в буфер ответа.

При использовании фрагментированного кодирования HTTP 1.1 (что означает, что ответ имеет заголовок Transfer-Encoding), не устанавливайте заголовок Content-Length.

...

При обычном кодировании данные отправляются как один непрерывный блок.

actualContent

При кодировании по частям данные отправляются порциями, которые выглядят следующим образом.

part1LengthInHexadecimal
actualPart1Content

part2LengthInHexadecimal
actualPart2Content

part3LengthInHexadecimal
actualPart3Content

0

Длина части в шестнадцатеричном формате указывает клиенту, насколько велика следующая порция данных (чтобы он случайно не проанализировал следующую порцию как часть текущей порции). Наконец, клиент склеивает детали. Кстати, это также поведение по умолчанию, когда в ответе используется Gzip, по очевидной причине, что окончательная длина содержимого заранее неизвестна.

См. также пример в википедии.

Обратите внимание, что если пропустить длину содержимого при загрузке файла, пользовательский опыт будет заключаться в том, что ход загрузки файла неизвестен. т.е. конечный пользователь не увидит никаких указаний на размер файла и оставшиеся байты/время. Если этот пользовательский опыт важен для вас, вам следует заранее установить длину контента. Вы можете сделать это, сначала записав в буфер в памяти (например, new ByteArrayOuputStream(bytes) или во временный файл (например, Files#createTempFile()), чтобы вы могли получить длину содержимого на bytes.length или file.length(), а затем, наконец, записать этот временный буфер/файл в ответ.

person BalusC    schedule 17.01.2013
comment
+1 но несколько придирок. Попытки установить длину контента из приложения будут игнорироваться в любом случае. Контейнер сервлета всегда либо устанавливает его, либо разбивает ответ на части. Я думаю, что ваши 2k находятся на низкой стороне, по крайней мере, для Tomcat, но у меня нет никаких ссылок со мной. - person user207421; 17.01.2013