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());

Тож ви можете перевірити зображення одразу в памʼяті, навіть не зберігаючи його на диск.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ