getContentLengthLong() == -1 means no known content length in the available metadata. Continue reading the stream and display received bytes or indeterminate progress; do not treat it as an empty response or allocate a negative-sized buffer.

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;
    }
}

The connection is already configured and the caller owns output. Keep connection/read timeouts and any application size limit around this loop. An I/O error is a failed download, not successful completion with fewer bytes.

Compare lengths at the same layer. HTTP/1.1 chunked coding can replace Content-Length and is decoded by the HTTP implementation. A proxy may reframe it. Decompression can also make the application's decoded byte count differ from an encoded Content-Length.

If both Transfer-Encoding and Content-Length appear, do not choose a convenient number: HTTP framing gives transfer coding precedence and treats the combination as a possible error. Leave that parsing to a conforming implementation.

An FTP URL through an HTTP gateway needs its concrete URLConnection behavior checked; it does not guarantee every HTTP header accessor behaves as on an ordinary HTTP URL in every JDK. Use the long-valued length API where metadata matters, and validate the completed artifact against the length or checksum actually required. Reading the body does not make a previously absent header appear.

Artihkkalat mat laktásit