Использование ServletOutputStream для записи очень больших файлов в сервлете Java без проблем с памятью

Вот ссылка, которая предлагает несколько вариантов. Я искал простую спецификацию, которой я мог следовать, вместо того, чтобы полагаться на частично определенный.

http://justinsomnia.org/writings/naming_conventions.html

37
задан Robert 3 July 2015 в 10:09
поделиться

7 ответов

Средний приличный контейнер сервлетов очищает поток по умолчанию каждые ~ 2 КБ. Вам действительно не нужно явно вызывать flush () в OutputStream из HttpServletResponse через определенные промежутки времени при последовательной потоковой передаче данных из одного и того же источника. Например, в Tomcat (и Websphere!) Это можно настроить как атрибут bufferSize коннектора HTTP.

Средний приличный контейнер сервлетов также просто передает данные в фрагментах , если длина содержимого заранее неизвестна (согласно спецификации API сервлетов !) И если клиент поддерживает HTTP 1.1.

По крайней мере, симптомы проблемы указывают на то, что контейнер сервлетов буферизует весь поток в памяти перед сбросом. Это может означать, что заголовок длины содержимого не установлен и / или контейнер сервлетов не поддерживает фрагментированное кодирование и / или клиентская сторона не поддерживает фрагментированное кодирование (то есть использует HTTP 1.0).

Чтобы исправить то или иное, просто заранее установите длину содержимого:

response.setHeader("Content-Length", String.valueOf(new File(path).length()));
43
ответ дан 27 November 2019 в 02:48
поделиться

Делает flush работа над потоком вывода.

Действительно я хотел прокомментировать, что необходимо использовать форму с тремя аргументами записи, поскольку буфер не обязательно полностью читается (особенно в конце файла (!)). Также попытка/наконец была бы в порядке, если Вы не хотите, чтобы Вы сервер неожиданно умерли.

1
ответ дан 27 November 2019 в 02:48
поделиться

Я использовал класс, который переносит outputstream для создания этого допускающим повторное использование в других контекстах. Это работало хорошо на меня в получении данных к браузеру быстрее, но я не посмотрел на последствия памяти. (простите мое устаревшее m_ именование переменной),

import java.io.IOException;
import java.io.OutputStream;

public class AutoFlushOutputStream extends OutputStream {

    protected long m_count = 0;
    protected long m_limit = 4096; 
    protected OutputStream m_out;

    public AutoFlushOutputStream(OutputStream out) {
        m_out = out;
    }

    public AutoFlushOutputStream(OutputStream out, long limit) {
        m_out = out;
        m_limit = limit;
    }

    public void write(int b) throws IOException {

        if (m_out != null) {
            m_out.write(b);
            m_count++;
            if (m_limit > 0 && m_count >= m_limit) {
                m_out.flush();
                m_count = 0;
            }
        }
    }
}
1
ответ дан 27 November 2019 в 02:48
поделиться

Я также не уверен если flush() на ServletOutputStream работы в этом случае, но ServletResponse.flushBuffer() должен отправить ответ клиенту (по крайней мере, на 2,3 спецификации сервлета).

ServletResponse.setBufferSize() обещание звуков, также.

1
ответ дан 27 November 2019 в 02:48
поделиться

не связанный с Вашими проблемами памяти, цикл с условием продолжения должен быть:

while(bytesRead > 0);
0
ответ дан 27 November 2019 в 02:48
поделиться

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

1
ответ дан 27 November 2019 в 02:48
поделиться
  1. Класс Кевина должен закрывать поле m_out, если оно не равно null в операторе close(), мы же не хотим утечки информации?

  2. Помимо оператора ServletOutputStream.flush(), операция HttpServletResponse.flushBuffer() также может очищать буферы. Однако, похоже, что это специфическая деталь реализации, имеют ли эти операции какой-либо эффект, или поддержка длины http-контента мешает. Помните, что указание длины содержимого - это опция в HTTP 1.0, так что все должно быть просто потоком, если вы все промываете. Но я не вижу этого

1
ответ дан 27 November 2019 в 02:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: