PHP:来自图像字节的图像 mime 类型

Posted

技术标签:

【中文标题】PHP:来自图像字节的图像 mime 类型【英文标题】:PHP: image mime type from image bytes 【发布时间】:2020-09-13 15:06:14 【问题描述】:

简介

我有一个从数据库中检索到的 base64 图像字符串:$imageBase64Str

我需要从此内容中检索 mime 并显示图像。这就是以下代码的作用:

function imgMime($imgBytes)
    if(is_null($imgBytes))
        return(false);
    
    if(strlen($imgBytes)<12)
        return(false);
    
    $file = tmpfile();
    if(!fwrite($file,$imgBytes,12))
        fclose($file);
        return(false);
    
    $path = stream_get_meta_data($file)['uri'];
    $mimeCode=exif_imagetype($path);
    fclose($file);
    if(!$mimeCode)
        return(false);
    
    return(image_type_to_mime_type($mimeCode));


$imageBytes=base64_decode($imageBase64Str,true);
if(!$imageBytes)
    throw new Exception("cannot decode image base64");

$imageMime=imgMime($imageBytes);
if(!$imageMime)
    throw new Exception("cannot recognize image mime");

header('Content-type: '.$imageMime);
echo($imageBytes);

问题

这个解决方案的问题是它需要我将内容的前 12 个字节写入临时文件。我想知道是否有一种简单的方法可以避免这种情况,而无需手动维护一组 mime。另外,我想避免调用外部程序(例如通过exec),以便我的代码保持可移植性。

理想情况

我希望有一个像 exif_imagetype_from_bytes 这样的 php 函数。我的imgMime 函数会更简单:

function imgMime($imgBytes)
    if(is_null($imgBytes))
        return(false);
    
    if(strlen($imgBytes)<12)
        return(false);
    
    $mimeCode=exif_imagetype($imgBytes);
    if(!$mimeCode)
        return(false);
    
    return(image_type_to_mime_type($mimeCode));


$imageBytes=base64_decode($imageBase64Str,true);
if(!$imageBytes)
    throw new Exception("cannot decode image base64");

$imageMime=imgMime($imageBytes);
if(!$imageMime)
    throw new Exception("cannot recognize image mime");

header('Content-type: '.$imageMime);
echo($imageBytes);

编辑:基于所选答案的解决方案

非常感谢@Kunal Raut 的回答让我想出了以下解决方案:

function imgMime($imgBytes)
    if(is_null($imgBytes))
        return(false);
    
    if(strlen($imgBytes)<12)
        return(false);
    
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime=$finfo->buffer($imgBytes);
    if(strncmp($mime, "image/", 6) != 0)
        return(false);
    
    return($mime);


$imageBytes=base64_decode($imageBase64Str,true);
if(!$imageBytes)
    throw new Exception("cannot decode image base64");

$imageMime=imgMime($imageBytes);
if(!$imageMime)
    throw new Exception("cannot recognize image mime");

header('Content-type: '.$imageMime);
echo($imageBytes);

恕我直言,这个解决方案要优雅得多。

【问题讨论】:

简短回答:该功能不存在。是的,这很糟糕。长答案:garykessler.net/library/file_sigs.html 【参考方案1】:

这个解决方案的问题是它需要我将内容的前 12 个字节写入临时文件。我想知道是否有一种简单的方法可以避免这种情况,而无需手动维护一组 mime。

这是因为你的这部分代码

if(!fwrite($file,$imgBytes,12))
        fclose($file);
        return(false);
    

它让您在文件中写入至少 12 个字节的数据,然后让执行继续进行。您可以跳过此if() 并解决您的第一个问题。

我希望有一个像 exif_imagetype_from_bytes 这样的 php 函数。我的 imgMime 函数会更简单

是的,有这样一个函数可以返回 base64_decoded 字符串的类型。

finfo_buffer()

有关此功能的更多详细信息Click Here。

函数的使用

Check out this

【讨论】:

非常感谢@Kunal Raut,确实,这个finfo_buffer() 函数正是我所需要的。我会用你的解决方案更新我的问题。 很高兴为您提供帮助:)

以上是关于PHP:来自图像字节的图像 mime 类型的主要内容,如果未能解决你的问题,请参考以下文章

PHP 处理图像

无法在 PHP 中使用 MIME 类型“image/x-ms-bmp”从 BMP 创建 GD 图像资源

PHP 图像处理

PHP 图像处理

将 MIME 类型转换为文件扩展名 PHP

干预图像 - 如何上传 MIME 类型的图像:application/octet-stream