getContentLengthLong() == -1 означает, что в доступных метаданных нет известной длины содержимого. Продолжайте читать поток и показывайте полученные байты или неопределённый прогресс; не считайте это пустым ответом и не выделяйте буфер отрицательного размера.

long expected = connection.getContentLengthLong();
long received = 0;
byte[] buffer = new byte[8192];
try (InputStream input = connection.getInputStream()) {
    int count;
    while ((count = input.read(buffer)) != -1) {
        output.write(buffer, 0, count);
        received += count;
    }
}

Соединение уже настроено, и output принадлежит вызывающему. Сохраняйте тайм-ауты соединения и чтения, а также любое ограничение размера приложения вокруг этого цикла. Ошибка ввода-вывода — это неудачная загрузка, а не успешное завершение с меньшим числом байтов.

Сравнивайте длины на одном уровне. Chunked-кодирование HTTP/1.1 может заменять Content-Length, и его декодирует реализация HTTP. Прокси может переформатировать его. Распаковка тоже может сделать декодированное число байтов приложения отличным от закодированного Content-Length.

Если присутствуют и Transfer-Encoding, и Content-Length, не выбирайте удобное число: кадрирование HTTP отдаёт приоритет транспортному кодированию и считает сочетание возможной ошибкой. Оставьте этот разбор соответствующей реализации.

URL FTP через HTTP-шлюз требует проверки конкретного поведения URLConnection; он не гарантирует, что каждый доступ к заголовку HTTP ведёт себя как на обычном HTTP URL в любой JDK. Используйте length API с длинным значением там, где важны метаданные, и проверяйте готовый артефакт по действительно требуемой длине или контрольной сумме. Чтение тела не заставляет ранее отсутствовавший заголовок появиться.

Похожие статьи