Если фактическая длина содержимого ответа полностью помещается в буфер ответа, который обычно составляет 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