Загрузки через Java-прокси, когда getContentLengthLong возвращает -1
Обрабатывайте неизвестный Content-Length при загрузке через прокси, не считая отсутствие метаданных размера пустым ответом.
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 с длинным значением там, где важны метаданные, и проверяйте готовый артефакт по действительно требуемой длине или контрольной сумме. Чтение тела не заставляет ранее отсутствовавший заголовок появиться.