【问题标题】:What is the best way to determine whether or not a file is an image in PHP?确定文件是否是 PHP 中的图像的最佳方法是什么?
【发布时间】:2026-01-07 08:55:01
【问题描述】:

我有一个人们可以上传文件的服务器。问题是某些文件名被破坏(没有任何扩展名),所以我无法立即确定文件类型。这个问题分为两部分:对于确实具有文件名的文件,确定它是否是图像的最佳方法是什么? (只是 if/else if 列表很长?)其次,对于没有扩展名的文件,如何确定它们是否是图像?

【问题讨论】:

标签: php image file-upload


【解决方案1】:

您可以使用exif_imagetype()

<?php
    $type =exif_imagetype($image);

$type 是一个值

  1. IMAGETYPE_GIF
  2. IMAGETYPE_JPEG
  3. IMAGETYPE_PNG
  4. IMAGETYPE_SWF
  5. IMAGETYPE_PSD
  6. IMAGETYPE_BMP
  7. IMAGETYPE_TIFF_II(英特尔字节顺序)
  8. IMAGETYPE_TIFF_MM(摩托罗拉字节顺序)
  9. IMAGETYPE_JPC
  10. IMAGETYPE_JP2
  11. IMAGETYPE_JPX
  12. IMAGETYPE_JB2
  13. IMAGETYPE_SWC
  14. IMAGETYPE_IFF
  15. IMAGETYPE_WBMP
  16. IMAGETYPE_XBM
  17. IMAGETYPE_ICO

来自手册:

当找到正确的签名时,将返回适当的常量值,否则返回值为 FALSE。返回值与 getimagesize() 在索引 2 中返回的值相同,但 exif_imagetype() 更快。

【讨论】:

  • 在 php 中,您可以使用 @: @exif_imagetype() 来抑制错误消息
  • 您需要后备。 exif_imagetype() 似乎并非在所有系统上都可用
【解决方案2】:

您可以使用 getimagesize 它不需要 GD 图像库,它返回有关图像类型的相同信息。 http://it2.php.net/manual/en/function.getimagesize.php

【讨论】:

  • 您可以使用@getimagesize('name-of-file') 来禁止对非图像文件发出警告
  • @chacham - 这不是错误,只是警告。如果文件无效,该函数返回 false,应使用getimagesize($filename) === false 进行检查。
  • 哪种方法需要GD?根据this link的说法,exif_imagetype不需要GD,但需要PHP使用--enable-exif编译。
【解决方案3】:

如果您启用了 GD2 扩展,您可以使用它来将文件加载为图像,然后如果它返回无效,您可以捕获错误并返回 FALSE,否则返回 TRUE。

【讨论】:

    【解决方案4】:

    这里有两种选择,一种是简单且预先构建但有一些不足之处,另一种是复杂且需要数学运算。

    PHP's fileinfo 可用于根据文件的实际头信息检测文件类型。例如,我刚刚抓住了你的引力:

    但实际代码是这样的:

    ‰PNG
    
    
    IHDR  szzô
    IDATX…­—OL\UÆZÀhëT)¡    c•1T:1‘Š‘.Ú(]4†A“ÒEY˜à.................................
    

    所以,即使没有文件名,我也可以很明显地检测到它。这就是 PHP Fileinfo 扩展要做的事情。大多数 PNG 和 JPG 文件都倾向于在其中包含此标头,但并非每种文件类型都如此。

    话虽如此,从手册来看,fileinfo 使用起来非常简单:

    $fi = new finfo(FILEINFO_MIME,'/usr/share/file/magic');
    $mime_type = $fi->buffer(file_get_contents($file));
    

    您的其他选择更复杂,这取决于您自己的个人野心,您可以generate a histogram and profile files based on their content

    这样的东西看起来像一个 GIF 文件:

    这样的东西看起来像一个 TIFF 文件:

    从那里您需要为多种类型的文件生成一个模型,以确定每种类型的直方图应该是什么,然后使用它来猜测。对于没有真正具有可轻松读取的“魔术头”的文件,这是一种很好的方法。请记住,您需要学习一些数学知识以及如何对平均直方图函数进行建模并将它们与文件进行匹配。

    【讨论】:

    • 我建议您也将这个答案发布在“原始”问题上,因为它看起来比现有的要好很多
    【解决方案5】:

    您可以尝试将图像加载到 PHP 的 GD 库中,看看是否有效。

    $file = file_get_contents('file');
    $img = imagecreatefromstring($file);
    if($img === FALSE){
      // file is NOT an image
    }
    else{
      // file IS an image
    }
    

    【讨论】:

      【解决方案6】:

      看图像魔术识别。 http://www.imagemagick.org/script/identify.php

      php 包装器在这里:http://www.php.net/manual/en/function.imagick-identifyimage.php

      或者,如果您只是想验证它是一张图片(而不关心元数据):http://www.php.net/manual/en/function.imagick-valid.php

      【讨论】:

        【解决方案7】:

        exif_imagetype() 可能会起作用

        确保您已启用 exif。

        【讨论】:

          【解决方案8】:

          试试看exif_imagetype

          【讨论】:

            【解决方案9】:

            如果您需要快速解决方案,请使用 imagesx() 和 imagesy()。还有一种快速检查大图像文件尺寸的方法,只需从文件头中读取少量数据。在以下网址中有更详细的解释:

            http://hungred.com/useful-information/php-fastest-image-width-height/

            【讨论】:

              【解决方案10】:

              您可以使用 Fileinfo 扩展名: http://www.php.net/manual/en/function.finfo-file.php

              finfo_file() 使用魔术字节并且不必将整个图像加载到内存中。结果是具有相应 MIME 类型的字符串,例如:

              • 文本/html
              • 图片/gif
              • 应用程序/vnd.ms-excel

              【讨论】:

                【解决方案11】:

                图像的类型通常可以从文件的标题信息中推断出来。

                【讨论】:

                  【解决方案12】:

                  第一个问题是扩展已知你可以使用PHP函数in_array()Documentation

                  【讨论】:

                    最近更新 更多