← Назад к вопросам

Что нужно сделать для получения картинки по HTTP?

1.6 Junior🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что нужно сделать для получения картинки по HTTP?

Получение картинки по HTTP в браузере — это базовый навык, но есть несколько способов и нюансов, которые нужно учитывать в зависимости от контекста использования.

Простейший способ: img тег

<!-- Самый простой способ -->
<img src="https://example.com/image.jpg" alt="Description" />

<!-- С атрибутами -->
<img 
  src="https://example.com/image.jpg" 
  alt="Описание изображения"
  width="300"
  height="200"
/>

Браузер автоматически сделает HTTP GET запрос и загрузит изображение. Это работает для любых форматов: JPG, PNG, WebP, GIF, SVG.

Через JavaScript: fetch API

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

// 1. Базовый способ
fetch("https://example.com/image.jpg")
  .then(response => response.blob())
  .then(blob => {
    const url = URL.createObjectURL(blob);
    const img = document.createElement("img");
    img.src = url;
    document.body.appendChild(img);
  })
  .catch(error => console.error("Ошибка загрузки:", error));

// 2. С async/await
const loadImage = async (imageUrl) => {
  try {
    const response = await fetch(imageUrl);
    if (!response.ok) throw new Error("HTTP " + response.status);
    
    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    
    const img = document.createElement("img");
    img.src = url;
    document.body.appendChild(img);
  } catch (error) {
    console.error("Ошибка:", error);
  }
};

loadImage("https://example.com/image.jpg");

Важные концепции

1. Blob и Object URL

// Fetch возвращает Response
const response = await fetch("/image.jpg");

// .blob() преобразует ответ в двоичные данные
const blob = await response.blob();
// blob это: { size: 12345, type: "image/jpeg" }

// URL.createObjectURL создаёт временную ссылку на blob
const url = URL.createObjectURL(blob);
// url это: "blob:https://example.com/550e8400-e29b-41d4-a716-446655440000"

// Используем URL в img тега
const img = new Image();
img.src = url;

// ВАЖНО: когда blob больше не нужен, освобождаем память
URL.revokeObjectURL(url);

2. Разные форматы ответа

// arrayBuffer — для обработки двоичных данных
const arrayBuffer = await response.arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer);

// blob — для создания Object URL (лучше для img)
const blob = await response.blob();
const url = URL.createObjectURL(blob);

// text — если это SVG как текст
const svgText = await response.text();
const dataUrl = `data:image/svg+xml,${encodeURIComponent(svgText)}`;

React компонент для загрузки картинок

import { useState, useEffect } from "react";

function ImageLoader({ imageUrl }) {
  const [src, setSrc] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    let objectUrl = null;
    
    const loadImage = async () => {
      try {
        const response = await fetch(imageUrl);
        if (!response.ok) throw new Error(`HTTP ${response.status}`);
        
        const blob = await response.blob();
        objectUrl = URL.createObjectURL(blob);
        setSrc(objectUrl);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    loadImage();
    
    // Очищаем memory leak
    return () => {
      if (objectUrl) URL.revokeObjectURL(objectUrl);
    };
  }, [imageUrl]);
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  
  return <img src={src} alt="Loaded" />;
}

Data URL

// Можно передать картинку как Data URL (для маленьких изображений)
const loadImageAsDataUrl = async (imageUrl) => {
  const response = await fetch(imageUrl);
  const blob = await response.blob();
  
  const reader = new FileReader();
  reader.onload = (e) => {
    const dataUrl = e.target.result;
    // dataUrl это: "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
    
    const img = new Image();
    img.src = dataUrl;
    document.body.appendChild(img);
  };
  reader.readAsDataURL(blob);
};

Canvas: рисование и обработка

const processImage = async (imageUrl) => {
  const img = await new Promise((resolve, reject) => {
    const image = new Image();
    image.crossOrigin = "anonymous"; // Для CORS
    image.onload = () => resolve(image);
    image.onerror = reject;
    image.src = imageUrl;
  });
  
  const canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  
  const ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);
  
  // Теперь можем:
  // 1. Получить пиксели
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  
  // 2. Применить фильтры
  const pixels = imageData.data;
  for (let i = 0; i < pixels.length; i += 4) {
    // [R, G, B, A]
    pixels[i] = pixels[i] * 0.8; // Уменьшить красный канал
  }
  ctx.putImageData(imageData, 0, 0);
  
  // 3. Экспортировать обратно
  const newUrl = canvas.toDataURL("image/png");
  return newUrl;
};

CORS проблемы

// Если сервер не разрешает CORS, нужно добавить заголовки

// ❌ Не сработает
fetch("https://other-domain.com/image.jpg")
  .then(res => res.blob());

// ✅ Может сработать с no-cors режимом
// (но не сможем прочитать данные)
fetch("https://other-domain.com/image.jpg", {
  mode: "no-cors"
});

// ✅ Лучше: использовать прокси или попросить сервер добавить CORS заголовки
// Access-Control-Allow-Origin: *
fetch("https://cors-proxy.example.com/?url=https://other-domain.com/image.jpg");

Оптимизация

1. Кэширование в IndexedDB

const cacheImageInDB = async (imageUrl) => {
  const response = await fetch(imageUrl);
  const blob = await response.blob();
  
  const db = await openDB("ImageCache");
  db.put("images", { url: imageUrl, blob, timestamp: Date.now() });
};

const getCachedImage = async (imageUrl) => {
  const db = await openDB("ImageCache");
  const cached = await db.get("images", imageUrl);
  
  if (cached && Date.now() - cached.timestamp < 24 * 60 * 60 * 1000) {
    return URL.createObjectURL(cached.blob);
  }
  
  return null;
};

2. Lazy Loading

<!-- Браузер загружает только видимые картинки -->
<img src="image.jpg" loading="lazy" alt="Description" />

3. Responsive Images

<!-- Браузер выбирает оптимальный размер -->
<picture>
  <source srcset="image-small.jpg 480w, image-large.jpg 1080w" sizes="100vw" />
  <img src="image-large.jpg" alt="Description" />
</picture>

4. WebP формат

<!-- Современные браузеры загружают WebP, остальные PNG -->
<picture>
  <source srcset="image.webp" type="image/webp" />
  <img src="image.png" alt="Description" />
</picture>

Прогресс загрузки

const loadImageWithProgress = async (imageUrl, onProgress) => {
  const response = await fetch(imageUrl);
  const total = parseInt(response.headers.get("content-length"), 10);
  
  const reader = response.body.getReader();
  let loaded = 0;
  const chunks = [];
  
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    chunks.push(value);
    loaded += value.length;
    onProgress({ loaded, total, percent: (loaded / total) * 100 });
  }
  
  const blob = new Blob(chunks);
  const url = URL.createObjectURL(blob);
  return url;
};

loadImageWithProgress("/image.jpg", (progress) => {
  console.log(`${progress.percent.toFixed(2)}%`);
});

Резюме: способы получения картинки

СпособИспользованиеПреимуществаНедостатки
<img>Простое отображениеПросто, браузер управляет кэшемНет контроля
fetch().blob()Обработка перед отображениемПолный контрольБольше кода
CanvasОбработка пикселейФильтры, трансформацииСложно, CORS ограничения
Data URLВстроение в DOMНет доп. запросаРазмер в HTML
ПроксиОбход CORSРаботает вездеЗависит от прокси

Основное правило: Для простого отображения используй <img>, для обработки и контроля — fetch().blob().