Определение типа изображения из строки base64 в PHP
Можно ли узнать тип изображения, закодированного в виде строки base64 в PHP?
У меня нет метода доступа к исходному файлу изображения, только закодированная строка. Из того, что я видел, imagecreatefromstring()
Можно создать ресурс изображения из строкового представления (после того, как он был декодирован из base64), но он автоматически определяет тип изображения, а сам ресурс изображения является специальным представлением PHP. Если я захочу снова сохранить изображение в виде файла, я не буду знать, соответствует ли тип, в котором я его сохраняю, исходному типу, из которого было создано представление String.
8 ответов
FileInfo может сделать это для вас:
$encoded_string = "....";
$imgdata = base64_decode($encoded_string);
$f = finfo_open();
$mime_type = finfo_buffer($f, $imgdata, FILEINFO_MIME_TYPE);
Если вы не хотите использовать эти функции из-за их зависимостей, вы можете использовать первые байты данных:
function getBytesFromHexString($hexdata)
{
for($count = 0; $count < strlen($hexdata); $count+=2)
$bytes[] = chr(hexdec(substr($hexdata, $count, 2)));
return implode($bytes);
}
function getImageMimeType($imagedata)
{
$imagemimetypes = array(
"jpeg" => "FFD8",
"png" => "89504E470D0A1A0A",
"gif" => "474946",
"bmp" => "424D",
"tiff" => "4949",
"tiff" => "4D4D"
);
foreach ($imagemimetypes as $mime => $hexbytes)
{
$bytes = getBytesFromHexString($hexbytes);
if (substr($imagedata, 0, strlen($bytes)) == $bytes)
return $mime;
}
return NULL;
}
$encoded_string = "....";
$imgdata = base64_decode($encoded_string);
$mimetype = getImageMimeType($imgdata);
Решение, данное @Marc B, является лучшим для меня (если наша версия php> 5.3.0, в противном случае мы можем использовать решение, данное @Aaron Murgatroyd).
Я хотел бы дать небольшое дополнение к этому решению.
Чтобы получить тип изображения, вы можете сделать это так:
$split = explode( '/', $mime_type );
$type = $split[1];
На самом деле (если вы этого не знаете) тип mime для изображений: image / type и type может быть png или gif или jpeg или...
Надеюсь, что это может кому-то помочь, и спасибо @Marc B за его решение.
Полный список типов пантомимы вы можете посмотреть здесь:
Код ниже получит тип изображения из его типа mime.
<?php
$base64 = "data:image/png;base64,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";
$image_info = getimagesize($base64);
$extension = (isset($image_info["mime"]) ? explode('/', $image_info["mime"] )[1]: "");
echo $extension;
?>
Путь, показанный @Marc B, самый хороший.
Должен FInfo
недоступно, единственный другой способ, которым я знаю, - это сохранить данные в файл и запустить getimagesize()
в теме.
Если вы знаете минимальное количество о структуре формата файла, вы можете теоретически просматривать верхние байты файла, пока не сможете определить, какой это тип файла.
Например, изображение GIF всегда начинается со следующих байтов GIF89a
, Если вы можете найти эту строку в начале файла, вы можете быть достаточно уверены, что это изображение в формате GIF и абсолютно уверены, что это не какой-либо другой формат изображения. (тем не менее, это может быть текстовый файл, который начинается с "GIF89a"; вам нужно проанализировать больше файлов, чтобы быть абсолютно уверенным)
Аналогично, в файлах PNG есть строка PNG
довольно близко к началу (это не совсем в самом начале; опять же, вам нужно изучить особенности формата файла, чтобы помочь вам определить, сколько вам нужно знать, чтобы быть уверенным).
JPEG также содержит узнаваемые строки в своих заголовках, хотя они более разнообразны и сложны. Вы можете высматривать строку Exif
,
Получение определений форматов файлов определенно даст вам больше точности, но в зависимости от того, насколько точным вы должны быть, вы можете узнать достаточно о форматах файлов, просто открыв некоторые файлы изображений в двоичном редакторе, чтобы увидеть, как они структурированы.
Эти ресурсы могут помочь вам:
Вы можете использовать магические числа для определения типа MIME (проверьте здесь список подписей файлов ). Однако сигнатуры файлов не на 100% надежны, и вы можете легко столкнуться с ложными срабатываниями. Конечно, есть задачи, когда такого решения более чем достаточно.
Поэтому, если у вас есть строка Base64 и вы хотите идентифицировать ее MIME-тип с помощью файловых подписей, вам не нужно декодировать Base64. Гораздо более быстрый способ — сохранить подписи файлов в формате Base64 и просто проверить, начинается ли ввод с одной из них. Простой пример:
<?php
function detectMimeType(string $base64)
{
$signaturesForBase64 = [
'JVBERi0' => "application/pdf",
'R0lGODdh' => "image/gif",
'R0lGODlh' => "image/gif",
'iVBORw0KGgo' => "image/png",
'/9j/' => "image/jpeg"
];
foreach($signaturesForBase64 as $sign => $mimeType)
{
if(strpos($base64, $sign) === 0) {
return $mimeType;
}
}
return false;
}
var_dump(detectMimeType('R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=')); // image/gif
var_dump(detectMimeType('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC')); // image/png
var_dump(detectMimeType('JVBERi0xLjUKJYCBgoMKMSAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvRmlyc3QgMTQxL04gMjAvTGVuZ3')); // application/pdf
var_dump(detectMimeType('/9j/4AAQSkZJRgABAQAAZABkAAD/2wCEABQQEBkSGScXFycyJh8mMi4mJiYmLj41NTU1NT5EQUFBQUFBRERERERERERE')); // image/jpeg
Я получил это решение от этого Js Que-Answer
Кроме того: этот тоже работает правильно
Следуйте PHP.NET Fileinfo: -
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
foreach (glob("*") as $filename) {
echo finfo_file($finfo, $filename) . "\n";
}
finfo_close($finfo);