Определение типа изображения из строки 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);
Другие вопросы по тегам