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 は呼び出し側が所有します。このループの周囲で接続と読み取りのタイムアウト、およびアプリケーションのサイズ上限を維持してください。I/O エラーはダウンロードの失敗であり、より少ないバイト数での正常完了ではありません。

長さは同じ層で比較してください。HTTP/1.1 の chunked 符号化は Content-Length を置き換えることがあり、HTTP 実装によって復号されます。プロキシが再フレーミングする場合もあります。伸長により、アプリケーションの復号後バイト数が符号化された Content-Length と異なることもあります。

Transfer-Encoding と Content-Length の両方が現れる場合、都合のよい数値を選んではいけません。HTTP のフレーミングは転送符号化を優先し、その組み合わせを誤りの可能性として扱います。その解析は準拠した実装に任せてください。

HTTP ゲートウェイ経由の FTP URL は、具体的な URLConnection の挙動を確認する必要があります。すべての JDK で、すべての HTTP ヘッダーアクセサーが通常の HTTP URL と同じように振る舞うことは保証されません。メタデータが重要な場面では long 値の length API を使い、完成した成果物を実際に要求される長さやチェックサムに対して検証してください。本文を読んでも、以前は存在しなかったヘッダーが現れるわけではありません。

関連記事