При разработке веб-приложений нередко возникает задача сохранить изображение, которое передаётся не как загруженный файл, а как строка в формате Base64. Такой подход используется повсеместно: AJAX-загрузчики изображений, ответы внешних API, обработка данных с canvas, работа с веб-камерой в браузере. В этих случаях нужно декодировать строку и записать результат в файл на сервере средствами PHP.
Что такое Base64-строка изображения
Base64 — это способ кодирования бинарных данных в текстовый формат, использующий 64 символа ASCII. Изображение в формате Base64 обычно выглядит так:
|
1 |
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAA... |
Строка состоит из двух частей, разделённых запятой:
- Префикс —
data:image/jpeg;base64— указывает MIME-тип и метод кодирования - Данные — собственно закодированное содержимое файла
При сохранении в файл нужна только вторая часть — данные после запятой. Префикс предназначен для браузера (он позволяет отображать изображение без скачивания файла) и при декодировании не нужен.
Базовый код для сохранения Base64-изображения
Вот простой и рабочий код, который решает задачу в несколько строк:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<? $base64_string = "data:image/jpeg;base64, ...."; // Убираем префикс, если он есть (например, "data:image/png;base64,") if (str_contains($base64_string, ',')) { list(, $base64_string) = explode(',', $base64_string); } // Декодируем строку Base64 $image_data = base64_decode($base64_string); // Указываем путь и имя файла $file_path = 'image.jpg'; // Измените расширение, если формат изображения другой (jpg, gif и т.д.) // Сохраняем файл if (file_put_contents($file_path, $image_data)) { echo "Файл успешно сохранён: $file_path"; } else { echo "Ошибка при сохранении файла."; } ?> |
Разбор кода по строкам
str_contains($base64_string, ',')— проверяет, есть ли в строке префикс. Иногда Base64 передаётся уже без префикса (только данные), и тогдаexplodeне нуженexplode(',', $base64_string)— разбивает строку по запятой.list(, $base64_string)— берём только второй элемент массива (после запятой), игнорируя первый (префикс)base64_decode($base64_string)— декодирует текстовую строку обратно в бинарные данные изображенияfile_put_contents($file_path, $image_data)— записывает бинарные данные в файл. Возвращает количество записанных байт илиfalseпри ошибке
Автоматическое определение типа файла и расширения
Если вы не знаете заранее, какой формат изображения придёт — можно извлечь тип из префикса Base64-строки и подобрать расширение автоматически:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php function saveBase64Image(string $base64_string, string $save_dir = '/uploads/'): string|false { // Парсим MIME-тип из префикса if (preg_match('/^data:(image\/(\w+));base64,/', $base64_string, $matches)) { $mime_type = $matches[1]; // например, image/jpeg $extension = $matches[2]; // например, jpeg // Нормализуем расширение $ext_map = ['jpeg' => 'jpg', 'svg+xml' => 'svg']; $extension = $ext_map[$extension] ?? $extension; // Отрезаем префикс $base64_data = substr($base64_string, strpos($base64_string, ',') + 1); } else { // Нет префикса — считаем jpeg по умолчанию $base64_data = $base64_string; $extension = 'jpg'; } $image_data = base64_decode($base64_data); if ($image_data === false) { return false; } $filename = uniqid('img_', true) . '.' . $extension; $file_path = rtrim($save_dir, '/') . '/' . $filename; if (file_put_contents($file_path, $image_data) === false) { return false; } return $file_path; } // Использование: $path = saveBase64Image($base64_string, '/var/www/html/uploads'); echo "Сохранено: $path"; ?> |
Проверка размера и валидности изображения
Перед сохранением стоит убедиться, что данные не слишком большие и действительно являются изображением:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php // Проверяем размер (не более 5 МБ) $max_size = 5 * 1024 * 1024; // 5 MB в байтах if (strlen($image_data) > $max_size) { die("Ошибка: файл слишком большой"); } // Проверяем что это действительно изображение через GD $image = @imagecreatefromstring($image_data); if ($image === false) { die("Ошибка: данные не являются корректным изображением"); } imagedestroy($image); ?> |
Безопасность при сохранении загружаемых изображений
Никогда не доверяйте данным, полученным от пользователя. При обработке Base64-изображений важно:
- Проверять MIME-тип через
finfo, а не только через префикс строки — пользователь может передатьdata:image/jpeg;base64,с PHP-кодом внутри - Не использовать имя файла из запроса — генерируйте имя файла на сервере через
uniqid()илиrandom_bytes() - Сохранять файлы вне web-root или в директорию без исполнения PHP, чтобы нельзя было выполнить загруженный файл как скрипт
- Ограничивать допустимые расширения белым списком:
['jpg', 'jpeg', 'png', 'gif', 'webp']
Примеры использования
AJAX-загрузка изображения с canvas
Типичный сценарий: пользователь редактирует изображение в браузере (обрезка, поворот), JavaScript конвертирует результат через canvas.toDataURL() и отправляет Base64 на сервер через AJAX. PHP принимает строку через $_POST['image'] или JSON и сохраняет файл описанным выше методом.
Обработка ответа внешнего API
Некоторые API (например, генераторы изображений, сервисы обработки документов) возвращают изображение прямо в теле ответа в формате Base64. В этом случае PHP получает строку через file_get_contents() или cURL, декодирует JSON и сохраняет изображение на диск для дальнейшей обработки или показа пользователю.
