2017-01-03 7 views
1

У меня есть обработчик при развертывании сервера причала, который имеет ссылку на объект HttpServletResponse.Установка длины содержимого в объекте ответа HTTP после записи в его OutputStream

Я пишу содержание байт в Response.getOutputStream(), как показано ниже:

ServletOutputStream serlvetOutputStream = handlerContext.getResponse().getOutputStream(); 
... 
while(condition) { 
//read chunk from some source into byteBuffer 
servletOutputStream.write(byteBuffer, 0, lengthRead); 
} 

Но перед тем я могу писать записи(), я должен установить Content-Length клиент HTTP ожидает в ответ:

handlerContext.getResponse().setContentLength((int) length); //or as below 
handlerContext.getResponse().addHeader("Content-Length", String.valueOf(length)); 

Неспособность установить длину перед записью в OutputStream, приводит к «Ошибка размера файла неизвестно» во всплывающем окне на клиентском приложении Windows. Но в некоторых случаях я не знаю, какова будет длина, которая будет написана до тех пор, пока она не появится. Я не могу накапливать все данные, которые нужно прочитать заранее (потому что он может тайм-аут клиента для больших данных), поэтому он должен быть «chunked», то есть читать x килобайт, а затем писать x килобайт, пока условие не станет ложным.

Мой вопрос: есть ли способ динамически обновлять длину контента непосредственно перед записью? В вышеприведенном цикле я хочу установить длину содержимого, как если бы многие байты были доступны для записи, записи(), а затем обновляли его снова, когда он перемещался.

Если я обновляю длину содержимого в цикле, я получаю jetty.server.EoFexception.

+1

Если вы читаете данные chunked, и вы не можете буферизовать все данные на Java, то вы не можете узнать фактическую сумму, прочитанную. Есть ли вероятность, что вы могли бы оценить длину контента, или API, из которого вы читаете, дает некоторую оценку? –

+1

Как следует из названия, Content-Length является заголовком и может устанавливаться один раз только в начале вашего ответа. В зависимости от происхождения ваших данных (файл, blob и т. Д.), Посмотрите, есть ли у вас метаданные, из которых вы можете запросить ожидаемую длину перед потоковой передачей содержимого. В противном случае вам может потребоваться буфер для всего потока (в памяти или на диске), определить его длину и затем установить заголовок и запустить ответ. Наконец, если длина контента по-настоящему невозможно определить вверх, посмотрите на обновление клиента и посмотрите на HTTP-потоки или потоковые протоколы. –

+1

Заголовки могут быть отправлены только до фактического содержимого, так работает HTTP. –

ответ

2

Вам не нужно устанавливать длину содержимого. Это произойдет автоматически. У вас здесь проблема XY. У вас есть нераскрытое исключение, и вы думаете, что настройка длины контента решит его. Однако, поскольку вы также не можете установить длину контента, у вас есть нулевые фактические данные для вашей веры.

+0

Клиент является приложением Windows, и он выдает сообщение об ошибке, если отсутствует длина содержимого. – PKM

+0

It бросает * что * исключение? И где ваши доказательства того, что поставка длины контента исправит это? – EJP

+0

Если я вручную установил длину контента для известного размера контента, он не стал жаловаться. Я видел (используя Wireshark), что клиент имеет пакет с длиной контента. Изменил бы «Исключение» на клиенте с «ошибкой» - всплывающее окно с надписью «Неизвестный размер ошибки». – PKM