[РУКОВОДСТВО] 11 мин чтения

[РУКОВОДСТВО] Как сделать предварительный просмотр Base64-изображений в браузере

Пять проверенных способов отобразить Base64-изображение на странице — прямое присваивание src, FileReader, canvas, конвертация в blob и паттерны под конкретные фреймворки. С советами по отладке.

April 2026 | javascript

// ОТВЕТ ЗА 30 СЕКУНД

Если у вас есть Base64-кодированная строка изображения и вы просто хотите увидеть её на странице, кратчайший путь — присвоить её как data: URI к img.src. Три строки JavaScript:

const img = new Image();
img.src = 'data:image/png;base64,' + base64String;
document.body.appendChild(img);

// If the string already starts with 'data:image/...;base64,'
// — just assign it directly without prepending anything:
img.src = base64StringWithDataUriPrefix;

// СПОСОБ 1: img.src — ПРЯМОЙ ПОДХОД

Любой элемент <img> воспринимает data URI как обычный URL. Присвойте URI свойству src, и браузер сам займётся декодированием, определением формата и отрисовкой.

Это работает для любого формата, который браузер поддерживает нативно: PNG, JPEG, GIF (анимированный и статический), WebP, SVG, BMP, ICO. Base64-строка может прийти откуда угодно — из ответа API, localStorage, вставки из буфера обмена, строки в БД.

MIME-тип в data URI важен для старых браузеров и некоторых встроенных WebView. Если у вас только сырая Base64-полезная нагрузка (без префикса data:) и вы не знаете формат, можно либо проверить магические байты (см. Способ 5), либо по умолчанию использовать image/png — большинство браузеров «принюхаются» и восстановятся, даже если MIME-тип неверен.

// Plain HTML — no JavaScript needed if the string is static
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..." alt="preview">

// Dynamic JavaScript — load from a variable, fetch, or input field
function renderBase64Image(base64, mimeType = 'image/png', containerId = 'preview') {
  const container = document.getElementById(containerId);
  const img = new Image();

  img.onload = () => {
    container.innerHTML = '';
    container.appendChild(img);
  };

  img.onerror = () => {
    container.textContent = 'Invalid image data';
  };

  // Tolerate both raw Base64 and full data: URIs
  img.src = base64.startsWith('data:')
    ? base64
    : `data:${mimeType};base64,${base64}`;
}

renderBase64Image(myBase64String, 'image/jpeg');

// СПОСОБ 2: FILEREADER ДЛЯ ФАЙЛОВ, ЗАГРУЖЕННЫХ ПОЛЬЗОВАТЕЛЕМ

Если пользователь загружает изображение через <input type="file">, вам не нужно вручную кодировать его в Base64. FileReader.readAsDataURL() отдаёт готовый data URI, который можно сразу же подставить в img.src:

<input type="file" id="fileInput" accept="image/*">
<img id="preview" alt="">

<script>
document.getElementById('fileInput').addEventListener('change', (e) => {
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();

  reader.onload = (event) => {
    // event.target.result is a complete data URI
    // e.g. 'data:image/png;base64,iVBORw0KGgo...'
    document.getElementById('preview').src = event.target.result;
  };

  reader.onerror = () => {
    console.error('FileReader failed:', reader.error);
  };

  reader.readAsDataURL(file);
});
</script>

// СПОСОБ 3: CANVAS ДЛЯ СГЕНЕРИРОВАННЫХ ИЛИ ИЗМЕНЁННЫХ ИЗОБРАЖЕНИЙ

Когда вы рисуете или обрабатываете изображение на <canvas>, canvas.toDataURL() экспортирует результат в data URI одним вызовом. Полезно для: скриншотов диаграмм, полей подписи, QR-кодов, водяных знаков и всего, что генерируется на стороне клиента и должно быть отображено или скачано как изображение.

// 1. Draw on canvas
const canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#00FF41';
ctx.fillRect(0, 0, 200, 200);
ctx.fillStyle = '#000';
ctx.font = '20px monospace';
ctx.fillText('Hello, Base64!', 20, 100);

// 2. Export to data URI
const pngDataURL = canvas.toDataURL('image/png');
// pngDataURL === 'data:image/png;base64,iVBORw0KGgo...'

// 3. Display directly
const img = new Image();
img.src = pngDataURL;
document.body.appendChild(img);

// JPEG with quality control (0–1)
const jpegDataURL = canvas.toDataURL('image/jpeg', 0.85);

// WebP if supported
const webpDataURL = canvas.toDataURL('image/webp', 0.9);

// СПОСОБ 4: FETCH + BLOB ДЛЯ УДАЛЁННЫХ BASE64-ПОЛЕЗНЫХ НАГРУЗОК

Если Base64-полезная нагрузка большая (более 50 КБ) или вы будете отображать её много раз, конвертация в Blob URL через URL.createObjectURL() экономнее по памяти, чем держать полный data URI в DOM. blob URL короткий (blob:https://example.com/12345-abcde), его можно отозвать, когда он больше не нужен, и он избавляет от 33% накладных расходов Base64 в строках DOM.

// Convert a Base64 string to a Blob, then to a blob: URL
function base64ToBlobURL(base64, mimeType = 'image/png') {
  // Strip the data: prefix if present
  const payload = base64.includes(',') ? base64.split(',')[1] : base64;

  // Decode Base64 to binary string
  const binary = atob(payload);

  // Convert binary string to Uint8Array
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }

  // Wrap in a Blob and create an object URL
  const blob = new Blob([bytes], { type: mimeType });
  return URL.createObjectURL(blob);
}

// Usage
const blobURL = base64ToBlobURL(myBase64, 'image/jpeg');
const img = new Image();
img.src = blobURL;
document.body.appendChild(img);

// IMPORTANT: free the memory when you're done with the image
img.onload = () => URL.revokeObjectURL(blobURL);

// СПОСОБ 5: АВТО-ОПРЕДЕЛЕНИЕ ФОРМАТА ПО МАГИЧЕСКИМ БАЙТАМ

Если вы получаете сырую Base64-полезную нагрузку (без префикса data:) и не знаете, PNG это, JPEG, GIF или WebP, загляните в первые декодированные байты — у каждого формата уникальная сигнатура.

function detectImageFormat(base64) {
  // Look at the first ~12 characters of the Base64 string
  const head = base64.replace(/^data:[^,]+,/, '').slice(0, 16);

  if (head.startsWith('iVBORw0KGgo')) return 'image/png';
  if (head.startsWith('/9j/'))         return 'image/jpeg';
  if (head.startsWith('R0lGOD'))       return 'image/gif';
  if (head.startsWith('UklGR'))        return 'image/webp';
  if (head.startsWith('PHN2Zy') ||
      head.startsWith('PD94bWw'))      return 'image/svg+xml';
  if (head.startsWith('Qk'))           return 'image/bmp';
  if (head.startsWith('AAABAA'))       return 'image/x-icon';

  return 'application/octet-stream'; // unknown
}

// Build a correct data URI even when the user only gave us the payload
function toDataURI(base64) {
  if (base64.startsWith('data:')) return base64; // already complete
  const mime = detectImageFormat(base64);
  return `data:${mime};base64,${base64}`;
}

// REACT — ОТОБРАЖЕНИЕ BASE64-ИЗОБРАЖЕНИЙ В КОМПОНЕНТАХ

В React относитесь к data URI как к любой другой строковой prop. Мемоизируйте конвертацию, если вход меняется редко:

import { useMemo } from 'react';

function Base64Image({ base64, mimeType = 'image/png', alt }) {
  const src = useMemo(() => {
    if (!base64) return '';
    return base64.startsWith('data:')
      ? base64
      : `data:${mimeType};base64,${base64}`;
  }, [base64, mimeType]);

  if (!src) return <div>No image</div>;
  return <img src={src} alt={alt} loading="lazy" />;
}

// Usage
<Base64Image
  base64={apiResponse.avatar}
  mimeType="image/jpeg"
  alt="User avatar"
/>

// For large images, prefer blob URLs (Method 4) and useEffect for cleanup:
function LargeBase64Image({ base64 }) {
  const [blobURL, setBlobURL] = useState('');

  useEffect(() => {
    const url = base64ToBlobURL(base64, 'image/png');
    setBlobURL(url);
    return () => URL.revokeObjectURL(url); // cleanup on unmount
  }, [base64]);

  return blobURL ? <img src={blobURL} alt="" /> : null;
}

// VUE 3 — ПРИМЕР НА COMPOSITION API

Та же идея, синтаксис Vue:

<script setup>
import { computed } from 'vue';

const props = defineProps({
  base64: String,
  mimeType: { type: String, default: 'image/png' },
  alt: { type: String, default: '' }
});

const src = computed(() => {
  if (!props.base64) return '';
  return props.base64.startsWith('data:')
    ? props.base64
    : `data:${props.mimeType};base64,${props.base64}`;
});
</script>

<template>
  <img v-if="src" :src="src" :alt="alt" loading="lazy" />
  <div v-else>No image</div>
</template>

// SVELTE — РЕАКТИВНОЕ ВЫРАЖЕНИЕ

<script>
  export let base64 = '';
  export let mimeType = 'image/png';
  export let alt = '';

  $: src = base64
    ? (base64.startsWith('data:') ? base64 : `data:${mimeType};base64,${base64}`)
    : '';
</script>

{#if src}
  <img {src} {alt} loading="lazy" />
{:else}
  <div>No image</div>
{/if}

// ОБРАБОТКА ОШИБОК — ЧТО ЛОМАЕТСЯ И ПОЧЕМУ

Изображение загружается как иконка-заглушка «битой картинки». Base64-полезная нагрузка обрезана, содержит пробелы внутри строки или использует URL-safe-символы (-_) внутри стандартного data URI. Удалите пробелы через str.replace(/\s+/g, ''); конвертируйте URL-safe обратно в стандартный через str.replace(/-/g, '+').replace(/_/g, '/'); и проверьте корректность длины (длина Base64 должна быть кратна 4 с правильным padding-ом =).

Изображение отрисовывается, но в неверном формате. Префикс data:image/png;base64, говорит, что это PNG, но реальные байты — JPEG. Браузер «принюхивается» к магическим байтам и всё равно отрисовывает корректно — но некоторые headless-браузеры и встроенные WebView так не делают. Используйте Способ 5, чтобы определить реальный формат по байтам.

Изображение огромно в DOM, и страница ощутимо тормозит. Base64-строка в 1 МБ внутри React-компонента ререндерится при каждом обновлении состояния. Переключитесь на blob: URL (Способ 4) — это строка из 50 символов в DOM независимо от размера изображения.

Изображение работает в Chrome, но не работает в Safari. У Safari более строгие настройки CSP по умолчанию, и он отвергает data: URI в некоторых контекстах (<a download>, fetch внутри service worker). Тестируйте в Safari и при необходимости откатывайтесь на blob: URL.

Сама Base64-строка некорректна. Иногда получаемый «Base64» оказывается дважды закодированным, hex-кодированным или просто повреждённым. Сначала вставьте его в наш декодер Base64 в изображение, чтобы убедиться в корректности данных, прежде чем отлаживать свой код.

// ПРОИЗВОДИТЕЛЬНОСТЬ: data: URI VS blob: URL — БЫСТРЫЙ БЕНЧМАРК

Для JPEG в 500 КБ, отображённого в <img>:

data: URI в src: 668 КБ строки в DOM (33% накладных расходов Base64). Браузер парсит URI, декодирует Base64, декодирует JPEG. ~80 мс до first paint на ноутбуке среднего уровня.
blob: URL через URL.createObjectURL: строка из 56 символов в DOM. Браузер забирает blob из памяти, декодирует JPEG. ~40 мс до first paint. ~50% экономии памяти.

Для иконки в 5 КБ разница незаметна — оба отрисовываются за < 5 мс. Вывод: до ~50 КБ — используйте то, что удобнее. Выше — предпочитайте blob URL.

// ИЗОЛИРОВАННОЕ ТЕСТИРОВАНИЕ ВАШЕГО ПРЕДВАРИТЕЛЬНОГО ПРОСМОТРА

Если вы подозреваете баг, сначала изолируйте Base64-строку от кода вашего приложения. Три быстрые проверки:

1. Вставьте её в наш онлайн-инструмент. Бросьте строку в конвертер Base64 в изображение. Если изображение там отрисовывается корректно — данные в порядке, и баг в вашем коде. Если и там не отрисовывается — данные повреждены вверх по потоку.

2. Откройте её как URL в новой вкладке. Скопируйте data URI (включая префикс data:image/png;base64,), вставьте в новую вкладку браузера, нажмите Enter. Современные браузеры отобразят изображение напрямую. (Некоторые блокируют data: в адресной строке — в этом случае пользуйтесь встроенным тестом из шага 1.)

3. Проверьте длину. Корректная Base64-строка имеет длину, кратную 4 (после удаления пробелов). Padding (=) добивает разницу: от 0 до 2 завершающих символов =. Если ваша длина не кратна 4, строка обрезана или растянута.

// Quick validation snippet
function looksLikeValidBase64(str) {
  const cleaned = str.replace(/^data:[^,]+,/, '').replace(/\s+/g, '');
  if (cleaned.length === 0) return false;
  if (cleaned.length % 4 !== 0) return false;
  if (!/^[A-Za-z0-9+/]+={0,2}$/.test(cleaned)) return false;
  return true;
}

// 30-СЕКУНДНАЯ ШПАРГАЛКА

Самый быстрый путь: присвойте data URI к img.src. Готово.

Из загрузки файла: FileReader.readAsDataURL(file).

Из canvas: canvas.toDataURL('image/png').

Для больших или повторяющихся изображений: сконвертируйте в blob и используйте URL.createObjectURL(blob).

Неизвестный формат: определите магические байты (iVBORw0KGgo = PNG, /9j/ = JPEG и т.д.) перед сборкой data URI.

Отладка: сначала вставьте в конвертер Base64 в изображение — это сразу исключит данные как источник проблемы.

Связанные материалы: Разбираем data URI · встраивание изображений в Base64 · Base64 в JavaScript: браузер и Node