response.flushBuffer () не работает

Я пытаюсь реализовать сервлет для потоковой передачи больших объектов:

    oracle.sql.BLOB blob = rs.getBLOB('obj');
    InputStream in = blob.getBinaryStream();

    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];

    ServletOutputStream out = response.getOutputStream();

    int counter=0
    while((length=in.read(buffer)) != -1){
        out.write(buffer,0,length);
        counter++;
        if(counter % 10 == 0){
        counter=0;
        response.flushBuffer();
    }

Этот код предполагает отправку данных клиенту по частям. Теперь происходит то, что при потоковой передаче большого объекта (100 МБ) увеличивается объем памяти, и иногда сервер умирает, если выполняется более одной параллельной загрузки / потока.

Почему flushBuffer() не отправляет данные клиенту? Клиент получает всплывающее окно для открытия / сохранения файла только после закрытия ответа.


person Madhu    schedule 11.05.2012    source источник
comment
Кроме того, я использую сервер JOBSS 4.3 для тестирования этого кода.   -  person Madhu    schedule 11.05.2012
comment
ты где-нибудь out.close()?   -  person andbi    schedule 11.05.2012
comment
да, я делаю out.close (), но не вставляю сюда   -  person Madhu    schedule 11.05.2012
comment
Он работает с небольшими потоками? Если да, там должны быть какие-то настройки, чтобы настроить это, я считаю, что установка уровня журнала на лучший может быть здесь полезна.   -  person andbi    schedule 11.05.2012
comment
Я считаю, что это конфигурация сервера приложений. См. мой пост.   -  person Igor Veloso    schedule 18.04.2017


Ответы (2)


Вы должны установить заголовок Content-Length перед записью данных, иначе сервер будет вынужден буферизовать все данные до закрытия потока, после чего он может вычислить само значение, записать заголовок и отправить все данные. Как только вы получите выходной поток, прежде чем вообще писать какие-либо данные, установите длину содержимого:

response.setHeader("Content-Length", String.valueOf(blob.length()));

Большинство серверов достаточно умны, чтобы очистить буфер самостоятельно на этом этапе, поэтому вам, вероятно, даже не нужно вызывать flushBuffer() - хотя это не повредит.

person Ernest Friedman-Hill    schedule 11.05.2012
comment
Я устал от этого. Это не случилось :-) - person Madhu; 11.05.2012
comment
В зависимости от ваших предпочтений вы также можете сделать response.setContentLength(blob.length()); - person Stuporman; 06.03.2013

Прежде всего, вам нужен заголовок ответа для ответа servlet, чтобы контейнер мог знать, через сколько байтов может закончиться информация:

response.setHeader("Content-Length", String.valueOf(blob.length()));
person GingerHead    schedule 11.05.2012