web-dev-qa-db-fra.com

Détecter le type d'image de la chaîne base64 dans PHP

Est-il possible de connaître le type d'une image encodée sous forme de chaîne base64 en PHP? 

Je n'ai aucune méthode pour accéder au fichier image d'origine, juste la chaîne encodée. D'après ce que j'ai vu, imagecreatefromstring() peut créer une ressource image à partir d'une représentation sous forme de chaîne (après le décodage en base64), mais détecte automatiquement le type d'image et la ressource elle-même est une représentation spéciale PHP. Si je souhaite enregistrer à nouveau l'image sous forme de fichier, je ne saurais pas si le type que je sauvegarde enregistre correspond au type d'origine à partir duquel la représentation sous forme de chaîne a été créée.

40
Epicurus

FileInfo peut le faire pour vous:

$encoded_string = "....";
$imgdata = base64_decode($encoded_string);

$f = finfo_open();

$mime_type = finfo_buffer($f, $imgdata, FILEINFO_MIME_TYPE);
88
Marc B

Si vous ne souhaitez pas utiliser ces fonctions en raison de leurs dépendances, vous pouvez utiliser les premiers octets des données:

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);
33
Aaron Murgatroyd

La solution proposée par @Marc B est la meilleure pour moi (si notre version php est> 5.3.0 sinon nous pouvons utiliser la solution proposée par @Aaron Murgatroyd).

Je voudrais ajouter un petit plus à cette solution.

Pour obtenir le type d'image, vous pouvez le faire comme ceci: 

$split = explode( '/', $mime_type );
$type = $split[1]; 

En fait, si vous ne le connaissez pas, le type mime des images est le suivant: image/type et type peuvent être png, gif ou jpeg ou ...

J'espère que cela peut aider quelqu'un et merci à @Marc B pour sa solution.

Pour une liste exhaustive des types de mime, vous pouvez regarder ici:

7
youssman

La façon indiquée par @Marc B est la plus agréable.

Si FInfo n'est pas disponible, le seul autre moyen que je connaisse consiste à stocker les données dans un fichier et à exécuter une getimagesize() dessus.

3
Pekka 웃

Si vous connaissez un minimum de connaissances sur la structure du format de fichier, vous pouvez théoriquement examiner les octets supérieurs du fichier jusqu'à ce que vous puissiez déterminer son type.

Par exemple, une image GIF commence toujours par les octets suivants GIF89a. Si vous pouvez trouver cette chaîne au début du fichier, vous pouvez être raisonnablement sûr qu'il s'agit d'une image GIF et absolument certain que ce n'est pas un autre format d'image. (cela pourrait quand même être un fichier texte, cela commence par "GIF89a"; vous devez analyser plus du fichier pour être absolument certain)

De même, dans les fichiers PNG, la chaîne PNG apparaît presque au début (ce n'est pas tout à fait au tout début; encore une fois, vous devez rechercher les spécificités du format de fichier pour vous aider à déterminer combien vous devez savoir pour être certain).

Les fichiers JPEG contiennent également des chaînes reconnaissables dans leurs en-têtes, bien que celles-ci soient plus variées et complexes. Vous voudrez peut-être rechercher la chaîne Exif.

Obtenir les définitions de format de fichier vous donnerait certainement plus de précision, mais en fonction de votre précision, vous pourriez en apprendre suffisamment sur les formats de fichier en ouvrant simplement des fichiers image dans un éditeur binaire pour voir leur structure.

Ces ressources peuvent vous aider:

2
Spudley

Suivez 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);
0
Bikash Mondal