HttpURLConnection.getInputStream: примеры (JAVA)

Чтение HTTP-ответа через Java-поток
Раздел: Работа с HTTP (HTTP Client, URLConnection)
HttpURLConnection.getInputStream: InputStream

Описание и поведение метода

Метод getInputStream() класса java.net.HttpURLConnection возвращает объект InputStream, через который читается тело HTTP-ответа сервера. Подключение к серверу устанавливается автоматически при первом обращении к этому потоку, если соединение ещё не установлено.

Сигнатура: public InputStream getInputStream() throws IOException.

Аргументы: метод не принимает аргументов. Его поведение зависит от состояния объекта HttpURLConnection и предварительно заданных свойств: метода запроса (GET, POST и т. п.), флагов setDoOutput, заголовков, таймаутов, настройки редиректов и протокола (HTTP/HTTPS).

Возвращаемое значение: InputStream - поток с телом ответа. После чтения поток следует закрыть. Для определения длины ответа можно использовать getContentLength() или getContentLengthLong(). В случае ответа с кодом ошибки (обычно HTTP-коды 4xx и 5xx) метод может выбросить IOException; в таких случаях для чтения тела ошибки применяется getErrorStream().

Особенности поведения и исключения:

  • Если сервер вернул код ошибки, вызов getInputStream() обычно бросит IOException (часто FileNotFoundException при 404). Тогда можно прочитать поток ошибки через getErrorStream().
  • Вызов выполняет подключение автоматически, поэтому предварительный вызов connect() не обязателен.
  • При использовании POST или других методов с телом нужно установить setDoOutput(true) и записать данные в getOutputStream() до получения ответа.
  • При HTTPS возможны исключения SSL (например, SSLHandshakeException) при проблемах с доверительными сертификатами.
  • Тайм-ауты контролируются через setConnectTimeout и setReadTimeout, в противном случае могут возникать бесконечные ожидания.

Краткий совет по использованию: читать ответ через возвращённый поток, учитывать возможность ошибок и закрывать ресурсы. Для современных приложений рекомендуется рассмотреть Java HTTP Client (java.net.http) в Java 11+, однако HttpURLConnection всё ещё широко применяется и совместим с большим количеством сред.

Короткие примеры использования

Ниже приведены компактные примеры. В коде указаны ожидаемые результаты для демонстрации.

Пример 1. Простой GET

URL url = new URL("https://httpbin.org/get");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
try (InputStream in = con.getInputStream();
     BufferedReader r = new BufferedReader(new InputStreamReader(in))) {
    String line;
    while ((line = r.readLine()) != null) System.out.println(line);
}
{
  "args": {},
  "headers": { ... },
  "url": "https://httpbin.org/get"
}

Пример 2. POST с телом

URL url = new URL("https://httpbin.org/post");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
byte[] out = "name=John".getBytes(StandardCharsets.UTF_8);
con.setFixedLengthStreamingMode(out.length);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
try (OutputStream os = con.getOutputStream()) {
    os.write(out);
}
try (InputStream in = con.getInputStream()) {
    System.out.println(new String(in.readAllBytes(), StandardCharsets.UTF_8));
}
{
  "form": { "name": "John" },
  "headers": { ... }
}

Пример 3. Обработка ошибок (404)

URL url = new URL("https://httpbin.org/status/404");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
try (InputStream in = con.getInputStream()) {
    System.out.println(new String(in.readAllBytes(), StandardCharsets.UTF_8));
} catch (IOException e) {
    try (InputStream err = con.getErrorStream()) {
        if (err != null) System.out.println(new String(err.readAllBytes(), StandardCharsets.UTF_8));
        else System.out.println("No error body, response code: " + con.getResponseCode());
    }
}
HTTP/1.1 404 NOT FOUND
{ "message": "404 Not Found" }

Пример 4. Таймауты

URL url = new URL("https://httpbin.org/delay/5");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(1000); // 1 секунда
con.setReadTimeout(2000);    // 2 секунды
con.setRequestMethod("GET");
try (InputStream in = con.getInputStream()) {
    System.out.println(new String(in.readAllBytes(), StandardCharsets.UTF_8));
} catch (SocketTimeoutException e) {
    System.out.println("Timeout: " + e.getMessage());
}
Timeout: Read timed out

Похожие методы в Java

В экосистеме Java есть несколько близких по назначению механизмов:

  • getErrorStream() - возвращает поток с телом при ошибочных ответах сервера; используется вместо getInputStream(), когда тот бросил исключение.
  • getOutputStream() - для записи тела запроса (POST/PUT); важно вызвать до чтения ответа.
  • URL.openStream() - удобный способ получить InputStream из URL, но предоставляет меньше контроля над заголовками и поведением соединения.
  • java.net.http.HttpClient (Java 11+) - более современный API: асинхронная и синхронная отправка запросов, удобные конвертеры тела в String/ByteArray, встроенная поддержка HTTP/2 и TLS. Предпочтителен для новых проектов.

Когда выбирать: для простоты и быстрого доступа к телу можно использовать URL.openStream(); для гибкости и контроля над запросом лучше HttpURLConnection; для современных приложений с возможностью асинхронности и улучшенной поддержки протоколов предпочтительнее java.net.http.HttpClient.

Альтернативы в других языках

Краткие аналоги и отличия с примерами.

JavaScript (fetch)

fetch('https://httpbin.org/get')
  .then(r => r.text())
  .then(console.log);
{
  "args": {},
  "headers": { ... }
}

Отличие: fetch возвращает промис и объект Response с методами text(), json(), arrayBuffer().

PHP (cURL)

$ch = curl_init('https://httpbin.org/get');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($ch);
curl_close($ch);
{
  "args": {},
  "headers": { ... }
}

Python (requests)

import requests
r = requests.get('https://httpbin.org/get')
print(r.text)
{
  "args": {},
  "headers": { ... }
}

Отличия: удобные методы для доступа к телу и заголовкам, автоматическое декодирование контента.

C# (HttpClient)

using var client = new HttpClient();
var s = await client.GetStringAsync("https://httpbin.org/get");
Console.WriteLine(s);
{
  "args": {},
  "headers": { ... }
}

Go (net/http)

resp, _ := http.Get("https://httpbin.org/get")
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
fmt.Println(string(b))
{
  "args": {},
  "headers": { ... }
}

Kotlin

val url = URL("https://httpbin.org/get")
(val url.openConnection() as HttpURLConnection).inputStream.bufferedReader().use { println(it.readText()) }
{ ... }

Lua (socket/http)

local http = require('socket.http')
local body, code = http.request('https://httpbin.org/get')
print(code, body)
200 { ... }

SQL

Стандартный SQL не содержит HTTP-клиента. В некоторых СУБД есть расширения или внешние функции (PostgreSQL: extension http, SQL Server: CLR/SQLCMD) для выполнения HTTP-запросов. Отличие: выполнение запроса через СУБД чаще служит для интеграции данных, но менее гибко и безопасно, чем клиентская библиотека.

В целом отличия между языками: модели асинхронности, удобство парсинга тела, поведение по умолчанию при редиректах и встроенная поддержка TLS/HTTP2 влияют на выбор аналога.

Типичные ошибки и их причины

Ниже - часто встречающиеся проблемы при работе с getInputStream() и примеры.

1. FileNotFoundException при 404

URL url = new URL("https://httpbin.org/status/404");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
InputStream in = con.getInputStream(); // бросит IOException / FileNotFoundException
java.io.FileNotFoundException: https://httpbin.org/status/404

Решение: вызвать getResponseCode() и при ошибке читать getErrorStream().

2. ProtocolException при попытке записать тело для GET

HttpURLConnection con = (HttpURLConnection) new URL("https://example.com").openConnection();
con.setRequestMethod("GET");
con.setDoOutput(true);
try (OutputStream os = con.getOutputStream()) { // может бросить
    os.write(...);
}
java.net.ProtocolException: cannot write to GET request

Причина: не все реализации поддерживают тело в GET; для тела следует использовать POST/PUT и соответствующие настройки.

3. SocketTimeoutException при долгом чтении

con.setReadTimeout(2000);
con.getInputStream(); // если сервер не присылает данные, через 2 сек возникнет исключение
java.net.SocketTimeoutException: Read timed out

4. SSLHandshakeException при проблемах с сертификатом

URL url = new URL("https://self-signed.badssl.com/");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.getInputStream();
javax.net.ssl.SSLHandshakeException: PKIX path building failed: ...

Причина: сертификат сервера не доверен. Решение: добавить корневой сертификат в хранилище, настроить TrustManager (только в контролируемой среде) или использовать HttpClient с кастомной конфигурацией TLS.

5. Невыполнение записи тела запроса перед чтением ответа

con.setDoOutput(true);
// забыли получить getOutputStream() и записать тело
try (InputStream in = con.getInputStream()) { ... }
Некорректный запрос на сервер или неожиданное поведение сервера

Решение: при использовании методов, требующих тела, сначала записать данные в getOutputStream(), затем читать ответ.

Изменения и эволюция API

Метод getInputStream() сам по себе в Java SE существенно не изменялся в последних релизах. Главные изменения в экосистеме:

  • В Java 11 появился java.net.http.HttpClient - современная альтернатива с поддержкой HTTP/2, асинхронными API и более удобной работой с телом ответов. Для новых проектов рекомендуется рассмотреть этот клиент.
  • HttpURLConnection остаётся поддерживаемым, но для новых возможностей (например, push-события HTTP/2, улучшенная производительность) стоит использовать HttpClient.
  • Внутренние исправления и улучшения стабильности в реализации JVM/пакетов проводились, но сигнатура и базовое поведение метода остались совместимыми назад.

Расширенные и неочевидные примеры

Дополнительные сценарии с пояснениями и выводом.

1. Скачивание большого файла с отображением прогресса

Пример java
URL url = new URL("https://speed.hetzner.de/100MB.bin");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
int length = con.getContentLength();
try (InputStream in = con.getInputStream();
     FileOutputStream out = new FileOutputStream("100MB.bin")) {
    byte[] buf = new byte[8192];
    int read;
    long total = 0;
    while ((read = in.read(buf)) != -1) {
        out.write(buf, 0, read);
        total += read;
        System.out.printf("Downloaded %d/%d\r", total, length);
    }
}
Downloaded 104857600/100000000

Пояснение: используется буфер, чтение в цикле и content-length для оценки прогресса; при chunked-encoding content-length может быть -1.

2. Автоматическая распаковка gzip

Пример java
HttpURLConnection con = (HttpURLConnection) new URL("https://httpbin.org/gzip").openConnection();
con.setRequestProperty("Accept-Encoding", "gzip");
try (InputStream raw = con.getInputStream()) {
    String enc = con.getHeaderField("Content-Encoding");
    InputStream in = "gzip".equalsIgnoreCase(enc) ? new java.util.zip.GZIPInputStream(raw) : raw;
    System.out.println(new String(in.readAllBytes(), StandardCharsets.UTF_8));
}
{ "gzipped": true, ... }

Пояснение: сервер может вернуть сжатое тело; нужно проверить заголовок Content-Encoding и при необходимости распаковать.

3. HTTPS с кастомным TrustManager (только для тестов)

Пример java
// Внимание: отключение проверки сертификатов делает соединение небезопасным
TrustManager[] trustAll = new TrustManager[]{ new X509TrustManager() { ... } };
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAll, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
URL u = new URL("https://self-signed.example/");
try (InputStream in = u.openStream()) { System.out.println(in.readAllBytes().length); }
5123

Пояснение: пример демонстрационный. В продакшене лучше установить доверенные сертификаты через keystore.

4. Multipart upload (файл и поля)

Пример java
String boundary = "----MyBoundary" + System.currentTimeMillis();
HttpURLConnection con = (HttpURLConnection) new URL("https://httpbin.org/post").openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (OutputStream out = con.getOutputStream();
     PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8), true)) {
    writer.append("--" + boundary).append("\r\n");
    writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"a.txt\"\r\n");
    writer.append("Content-Type: text/plain\r\n\r\n");
    writer.append("hello").append("\r\n");
    writer.append("--" + boundary + "--\r\n");
}
try (InputStream in = con.getInputStream()) { System.out.println(new String(in.readAllBytes(), StandardCharsets.UTF_8)); }
{ "files": { "file": "hello" }, ... }

Пояснение: ручная сборка multipart. Для сложных задач удобно использовать библиотеки.

5. Работа через прокси

Пример java
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 3128));
HttpURLConnection con = (HttpURLConnection) new URL("http://example.com").openConnection(proxy);
try (InputStream in = con.getInputStream()) { System.out.println(in.readAllBytes().length); }
1024

Пояснение: через Proxy можно направлять запросы на корпоративный прокси; для прокси с аутентификацией потребуется заголовок Authorization или Authenticator.

6. Асинхронная обработка тела (в потоках)

Пример java
// HttpURLConnection сам по себе синхронный, но чтение потока можно выполнять в отдельном потоке
ExecutorService ex = Executors.newSingleThreadExecutor();
HttpURLConnection con = (HttpURLConnection) new URL("https://httpbin.org/stream/10").openConnection();
Future<Integer> f = ex.submit(() -> {
    try (InputStream in = con.getInputStream()) {
        int lines = 0;
        BufferedReader r = new BufferedReader(new InputStreamReader(in));
        while (r.readLine() != null) lines++;
        return lines;
    }
});
System.out.println("Lines: " + f.get());
ex.shutdown();
Lines: 10

Пояснение: для неблокирующей логики чтение выполняется в отдельном потоке; альтернативой является java.net.http.HttpClient с CompletableFuture.

джава HttpURLConnection.getInputStream function comments

En
HttpURLConnection.getInputStream Returns an input stream that reads from this open connection