JavaRush /Курсы /JAVA 25 SELF /Скачиваем картинки из интернета

Скачиваем картинки из интернета

JAVA 25 SELF
12 уровень, 4 лекция
Открыта

1. Введение

Работа с файлами и сетью — одна из важнейших тем в программировании. Почти любое современное приложение так или иначе взаимодействует с интернетом: загружает данные, отправляет запросы, получает изображения или документы. Даже простая программа вроде чат-клиента или музыкального проигрывателя обязательно имеет дело с загрузкой ресурсов.

Сегодня мы разберёмся, как это делать в Java, на примере самого наглядного и приятного груза — картинок. Почему именно они?

  • Видно сразу: Если всё сработало, вы просто открываете скачанный файл и видите изображение. Это моментальный и понятный результат.
  • Универсальный навык: Картинки — это не просто картинки, а бинарные данные, “сырые байты”. Научившись работать с ними, вы сможете скачивать что угодно: документы, видео, музыку, архивы. Принцип один и тот же!
  • Реальные задачи: Умение скачивать ресурсы из сети — это фундамент для создания любого современного приложения, от простых загрузчиков обоев до сложных систем, работающих с API социальных сетей.

Мы разберёмся двумя подходами: быстрый “почтовый сервис” — через URL, и “профессиональная транспортная компания” — через HttpClient с контролем заголовков, статусов и тайм-аутов.

2. Простейший способ: класс URL

В Java есть класс URL, который представляет собой сетевой адрес. Он позволяет открыть соединение и получить поток данных (тип InputStream). С этим потоком можно работать так же, как с файлом: читать байты, копировать в другой поток, обрабатывать как текст.

По сути, использование URL — это самый короткий путь от ссылки в браузере до файла на диске.

Первый минимальный пример

Предположим, у нас есть ссылка на картинку:

URL url = new URL("https://example.com/image.jpg");
Files.copy(url.openStream(), Path.of("a.jpg"));

Всего две строчки. Что здесь происходит?

  1. Создаём объект URL, передавая ему строку с адресом картинки.
  2. Вызываем метод openStream(), который открывает сетевое соединение и возвращает поток InputStream.
  3. С помощью метода Files.copy копируем содержимое потока в файл "a.jpg".

Результат: картинка из интернета сохраняется в нашу рабочую папку.

Вариант с transferTo

Есть ещё один способ переправить данные из потока в файл:

InputStream in = new URL("https://example.com/image.jpg").openStream();
in.transferTo(Files.newOutputStream(Path.of("b.jpg")));

Здесь мы явно говорим: возьми поток in и «перекачай» все данные методом transferTo в поток, который записывает файл "b.jpg".

Результат будет тот же: картинка окажется на диске.

Важные детали

Такой подход очень прост, но у него есть нюансы. Во-первых, мы никак не проверяем, что именно пришло по ссылке. Может быть, это картинка. А может быть — HTML-страница с ошибкой 404. В обоих случаях файл сохранится. Разница будет заметна только потом, когда вы попробуете открыть его в просмотрщике изображений.

3. Современный способ: HttpClient

Начиная с Java 11 в стандартную библиотеку вошёл новый инструмент — HttpClient. Он позволяет делать HTTP-запросы на современном уровне: работать с методами GET, POST и другими, управлять тайм-аутами, следить за заголовками и статусами, обрабатывать редиректы.

Для скачивания картинок это особенно полезно: мы можем убедиться, что файл действительно загружен успешно, а не получена ошибка.

Минимальный пример с HttpClient

URI uri = URI.create("https://example.com/image.jpg");   // URI - более современная версия URL

HttpClient client = HttpClient.newHttpClient();          // Создаем объект HttpClient
HttpRequest request = HttpRequest.newBuilder(uri).build(); // Создаем объект "запрос"

HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
Files.write(Path.of("c.jpg"), response.body());

Теперь по шагам:

  1. Создаём клиента HttpClient.
  2. Конструируем запрос HttpRequest на указанный адрес.
  3. Отправляем запрос и получаем ответ как массив байтов: HttpResponse.BodyHandlers.ofByteArray().
  4. Записываем эти байты в файл методом Files.write — "c.jpg".

Результат — та же картинка, но теперь у нас есть больше информации о том, как именно сервер ответил.

Проверка статуса ответа

У объекта response есть метод statusCode(). С его помощью можно убедиться, что сервер вернул успешный ответ:

if (response.statusCode() == 200)
{
    Files.write(Path.of("ок.jpg"), response.body());
}
else
{
    System.out.println("Ошибка: код " + response.statusCode());
}

Теперь мы точно знаем, что сохранили именно то, что ожидали, а не страницу с ошибкой.

Получение заголовков

Допустим, мы хотим проверить тип содержимого:

String type = response.headers().firstValue("Content-Type").orElse("неизвестно");
System.out.println("Тип содержимого: " + type);

Если сервер вернул "image/png" или "image/jpeg", значит это действительно картинка. Если же пришло "text/html", это тревожный сигнал.

Тайм-ауты

Чтобы программа не зависла, если сервер долго отвечает, можно задать ограничение:

URI uri = URI.create("https://example.com/image.jpg");
HttpRequest req = HttpRequest.newBuilder(uri)
    .timeout(Duration.ofSeconds(5))
    .build();

Если сервер не ответит за 5 секунд, запрос завершится ошибкой.

Обработка редиректов

Иногда ссылки ведут не напрямую к файлу, а сначала на страницу-перенаправление. Включить автоматическое следование за редиректами можно так:

HttpClient client = HttpClient.newBuilder()
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build();

4. Практические сценарии

Загрузка нескольких картинок подряд

Часто требуется скачать не одну, а десятки или сотни картинок. Например, вы пишете программу, которая сохраняет аватарки пользователей или фотографии товаров. С помощью HttpClient это делается циклом:

var client = HttpClient.newHttpClient();

String[] urls = {
    "https://example.com/img1.jpg",
    "https://example.com/img2.jpg"
};

for (int i = 0; i < urls.length; i++)
{
    var uri = URI.create(urls[i]);
    var request = HttpRequest.newBuilder(uri).build();
    var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
    if (response.statusCode() == 200) {
        Files.write(Path.of("img" + i + ".jpg"), response.body());
    }
}

Проверка размера файла

Бывает полезно узнать, сколько байтов в картинке. Сервер может сообщить это в заголовке "Content-Length":

String length = response.headers().firstValue("Content-Length").orElse("?");
System.out.println("Размер: " + length + " байт");

Если заголовка нет, всегда можно просто взять response.body().length.

Загрузка и отображение картинки в программе

Иногда картинку нужно не только скачать, но и сразу показать. Для этого можно использовать библиотеку javax.imageio.ImageIO:

InputStream in = new URL("https://example.com/pic.png").openStream();
BufferedImage img = ImageIO.read(in);
System.out.println("Ширина: " + img.getWidth() + ", высота: " + img.getHeight());

Таким образом, мы можем проверить картинку сразу в памяти, даже не сохраняя её на диск.

1
Задача
JAVA 25 SELF, 12 уровень, 4 лекция
Недоступна
Скачивание файла через URL
Скачивание файла через URL
1
Задача
JAVA 25 SELF, 12 уровень, 4 лекция
Недоступна
Скачивание файла с помощью transferTo
Скачивание файла с помощью transferTo
1
Задача
JAVA 25 SELF, 12 уровень, 4 лекция
Недоступна
Скачивание файла через HttpClient
Скачивание файла через HttpClient
1
Задача
JAVA 25 SELF, 12 уровень, 4 лекция
Недоступна
Получение типа содержимого и размера файла
Получение типа содержимого и размера файла
Комментарии (25)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
rwnmei Уровень 57
16 августа 2026

client.send(request, HttpResponse.BodyHandlers.ofByteArray())
— это по сути: «Отправь запрос request на сервер и получи ответ, сохранив его содержимое в виде массива байтов byte[].»

client
—HTTP-клиент, который общается с сервером.

send()
— отправляет запрос и ждёт ответ.

reguest
— сам запрос: куда и что мы хотим получить.

BodyHandlers.ofByteArray()
— говорит Java: «тело ответа сохрани как byte[] И в итоге

HttpResponse<byte[]> response = client.send(request, ...);
response содержит ответ сервера, а:

содержит сами данные — например, байты скачанной картинки.
response.body()
19 июля 2026
Классная тема. Первые задачи шли сложно, хоть были достаточно маленькие и простые, а последняя задача наоборот, после нескольких практических задач решилась быстро и с первого раза. Глаза боятся, а руки делают 🤠
3 июля 2026
Хахаха, все, кто писал "очень легкие задачи", столкнувшись с первыми трудностями, заплакали, что сложно? 😀
Anna Klushkina Уровень 2
13 июня 2026
⛏️ На такую объемную тему очень не хватает побольше задач, и очень желательно отдельного уровня. Задачи почти не откладываются на подкорку. Но сама тема и задачи хороши
Seveneight Уровень 23
12 июня 2026
Очень мало объясняется, очень много требуют задания. с такими лекциями пропадает желание что либо изучать. Лучше растянуть эту лекцию хотябы на несколько, если не на целый уровень.
StepV Уровень 1
17 апреля 2026
Слишком сложная лекция, тянет на целый урок. Учу java c 0, написано нереально сложно, прочитал и лекцию и доп статьи (например: https://javarush.com/quests/lectures/questservlets.level10.lecture01) а желания понимать этот урок всё ниже и ниже...
SomeJavaCoder Уровень 3
18 апреля 2026
Ну как успехи?
SomeJavaCoder Уровень 3
18 апреля 2026
Мне создание запросов к API больше зашло и моментально понятно стало, может как-то проще написано (та лекция, которую ты упомянул в скобках)
StepV Уровень 1
18 апреля 2026
Полностью согласен, след лекция куда понятнее и интереснее. А на эту я просто забил, попытал удачи в доп. статьях, gpt, но в итоге это единственная лекция в которой я не стал решать задачи
SomeJavaCoder Уровень 3
19 апреля 2026
Если честно, дальше тоже будет пару таких лекций, но там получилось решить честно только пару задач
SomeJavaCoder Уровень 3
21 марта 2026
Слишком много всего навалено, если честно даже пропало желание решать конкретно эту лекцию и задачки... Думаю, надо про каждый метод тут надо вводить в начале лекции и хотя бы пояснить чей он, от чего зависит, за что отвечает, а так ничего не понятно, если не читать дополнительные материалы с других курсов.
StepV Уровень 1
15 апреля 2026
Полностью поддерживаю!
Cherepoq Уровень 26
27 февраля 2026
Мдааа, бонусный уровень а по ощущениям 5 отдельных уровней сжатые в 1 лекцию
Yaroslav Уровень 30
27 ноября 2025
// Готовим GET-запрос к нужному URL Как? Да, этого не было в лекции... читаем здесь
15 декабря 2025
спасибо
Виктор Уровень 13
14 ноября 2025
Кайф, наконец-то что-то стоящее! а то все вода уровня старших классов. кто не осилил загуглите "http сервер клиент запрос ответ"