【问题标题】:How to get MIME type of a file in PHP 5.5?如何在 PHP 5.5 中获取文件的 MIME 类型?
【发布时间】:2014-06-10 19:50:47
【问题描述】:

我在 PHP 5.5 中使用 mime_content_type() 来获取 MIME 类型,但它会抛出 fatal: error function not found

如何在 PHP 5.5 上实现这一点?

【问题讨论】:

  • 您介意接受您的问题的答案吗?我知道这是不久前被问到的,但很高兴知道你的解决方案最终是什么:)

标签: mime-types deprecated php-5.5


【解决方案1】:

利用finfo() 函数。

一个简单的例子:

<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, "path/to/image_dir/image.gif");
finfo_close($finfo);

OUTPUT :

image/gif

注意:Windows 用户必须在 php.ini 中包含捆绑的 php_fileinfo.dll DLL 文件才能启用此扩展。

【讨论】:

  • 我收到致命错误:调用未定义的函数 finfo_open()。
  • @DOZ,那是因为 OP 可能正在使用 Windows,他需要手动操作。
  • @ShankarDamodaran 确切:)
  • 我已经激活了 php_fileinfo.dll 但仍然无法正常工作。 if($_SERVER['REQUEST_METHOD']=='POST'){ echo $_FILES['file']['name'].'&lt;br&gt;'; $finfo = finfo_open(FILEINFO_MIME_TYPE); echo finfo_file($finfo, $_FILES['file']['name']); finfo_close($finfo); } 显示的是名字而不是 Mime 类型。 :)
  • No 没有收到任何错误但仍然没有显示 Mimetype。
【解决方案2】:

我花了太多时间试图让 finfo 函数正常工作。我终于创建了自己的函数来将文件扩展名与任何 mime 类型数组匹配。这不是确保文件确实是扩展名所表示的文件的完全证明方式,但可以通过在服务器上处理所述文件的 I/O 来缓解这个问题。

function mime_type($file) {

    // there's a bug that doesn't properly detect
    // the mime type of css files
    // https://bugs.php.net/bug.php?id=53035
    // so the following is used, instead
    // src: http://www.freeformatter.com/mime-types-list.html#mime-types-list

    $mime_type = array(
        "3dml" => "text/vnd.in3d.3dml",
        "3g2" => "video/3gpp2",
        "3gp" => "video/3gpp",
        "7z" => "application/x-7z-compressed",
        "aab" => "application/x-authorware-bin",
        "aac" => "audio/x-aac",
        "aam" => "application/x-authorware-map",
        "aas" => "application/x-authorware-seg",
        "abw" => "application/x-abiword",
        "ac" => "application/pkix-attr-cert",
        "acc" => "application/vnd.americandynamics.acc",
        "ace" => "application/x-ace-compressed",
        "acu" => "application/vnd.acucobol",
        "adp" => "audio/adpcm",
        "aep" => "application/vnd.audiograph",
        "afp" => "application/vnd.ibm.modcap",
        "ahead" => "application/vnd.ahead.space",
        "ai" => "application/postscript",
        "aif" => "audio/x-aiff",
        "air" => "application/vnd.adobe.air-application-installer-package+zip",
        "ait" => "application/vnd.dvb.ait",
        "ami" => "application/vnd.amiga.ami",
        "apk" => "application/vnd.android.package-archive",
        "application" => "application/x-ms-application",
        // etc...
        // truncated due to Stack Overflow's character limit in posts
    );

    $extension = \strtolower(\pathinfo($file, \PATHINFO_EXTENSION));

    if (isset($mime_type[$extension])) {
        return $mime_type[$extension];
    } else {
        throw new \Exception("Unknown file type");
    }

}

编辑:

我想解决 Davuz 的评论(因为它不断获得投票)并提醒大家,我在顶部放置了伪免责声明,这不是“完全证明”。因此,在考虑我在回答中提供的方法时,请记住这一点。

【讨论】:

  • 如果你分享最终功能的链接,我会给你投票。)
  • 询问,您将收到:gist.github.com/Erutan409/…
  • 如果我将文件名“hamster.sh”更改为“hamster.jpg”会怎样?这简直是​​失败!
  • 如果您阅读了我的帖子/答案或查看了 gist 源 cmets,您将看到关于此的免责声明。我的建议是在上传时处理扩展欺骗。无论如何,你能做的只有这么多。你是控制文件的人。
  • 您应该使用$extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));,这样它还可以检测具有大写扩展名的文件的 mime 类型
【解决方案3】:

mime_content_type() 没有被弃用并且工作正常。

Why is mime_content_type() deprecated in PHP?

http://php.net/manual/en/function.mime-content-type.php

从 PHP 5.3 开始,它甚至是 built-in

【讨论】:

  • 赞成,但如果你不介意的话,我还需要编辑它:说它是“内置”是误导(至少它确实误导了我;)):你仍然需要fileinfo 扩展让它工作! (page you referred to 只说你可以重新编译分机。没有mime_magic 库。)
  • 他们改变了文本:) 它是内置的,在 Linux 中,但在 Windows 上,您需要在 php.ini 中包含 .dll。
【解决方案4】:

$finfo = finfo_open(FILEINFO_MIME_TYPE); 应该这样做。

取自 php.net 文档。您的函数已被弃用,可能已被删除。

http://www.php.net/manual/en/function.finfo-file.php

【讨论】:

  • 我收到致命错误:调用未定义的函数 finfo_open()。
  • @Jordan 在其他问题上说“PHP 5.3.0 及更高版本内置了 Fileinfo,但 在 Windows 上,您必须在 php.ini 中手动启用它。您可以找到文档中的更多信息。”
  • 具体来说,在您的 php.ini 中取消注释(删除 ;)这一行:;extension=php_fileinfo.dll
【解决方案5】:

使用以下方法获取图像大小:

$infFil=getimagesize($the_file_name);

echo $infFil["mime"]

getimagesize 返回一个关联数组,它有一个 MIME 键,显然还有图像大小

我用过,效果很好

【讨论】:

    【解决方案6】:

    你应该明白 file_get_contents 会将整个文件上传到内存中,仅获取 mime 类型不是好方法。在这种情况下,您不需要使用 buffer 方法和 file_get_contents 函数。

    为防止出现任何错误和警告,最好这样做。

    $filename = 'path to your file';
    
    if (class_exists('finfo')) {
        $finfo = new finfo(FILEINFO_MIME_TYPE);
        if (is_object($finfo)) {
            echo $finfo->file($filename);
        }
    } else {
        echo 'fileinfo did not installed';
    }
    

    你还应该知道,如果失败,$finfo->file 会抛出 PHP 警告。

    如果 fileinfo 没有正确安装,并且你有一个新版本的 PHP,你可以从 headers 中获取 mime 类型。

    您可以使用 cURL 从标题中获取 mime 类型。

        $ch = curl_init();
        curl_setopt_array($ch, array(
                CURLOPT_HEADER => true,
                CURLOPT_NOBODY => true,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 1,
                CURLOPT_URL => $link)
        );
    
        $headers = curl_exec($ch);
        curl_close($ch);
    
        if (preg_match('/Content-Type:\s(.*)/i', $headers, $matches)) {
            echo trim($matches[1], "\t\n\r");
        }else {
            echo 'There is no content type in the headers!';
        }
    

    你也可以使用get_headers函数,但它比cURL请求慢。

    $url = 'http://www.example.com';
    
    $headers = get_headers($url, 1);
    
    echo $headers['Content-Type'];
    

    【讨论】:

    • Content-Type 返回的值仅取决于扩展名,而不取决于真正的 MIME TYPE。因此,将 bad_file.exe 重命名为 good_file.doc 将返回 application/msword - 没有扩展名的文件返回 404。 php.net/manual/en/function.get-headers.php#80460
    • 你不能相信互联网上的一切。所以,@yckart,你认为让你的服务器过载并下载所有文件并通过内容进行检查会更好,这些内容也可以重写以防止内容类型检测? fileinfo虽然这不是万无一失的方法,但使用的启发式方法做得很好。,-php.net/manual/en/intro.fileinfo.php
    【解决方案7】:

    我使用 Bat (https://github.com/lingtalfi/Bat) 的 MimeTypeTool

    如果可用,它使用 fileinfo,否则默认返回“extension => mime type”映射。

    【讨论】:

      【解决方案8】:

      这是我通过结合两个非常好的帖子找到的最佳解决方案

      // 感谢http://php.net/manual/en/function.mime-content-type.php#87856

      function getMimeContentType($filename, $ext)
      {
          if(!function_exists('mime_content_type'))
          {
              if($mime_types = getMimeTypes())
              {
                  if (array_key_exists($ext, $mime_types))
                  {
                      return $mime_types[$ext];
                  }
                  elseif (function_exists('finfo_open'))
                  {
                      $finfo  = finfo_open(FILEINFO_MIME);
                      $mimetype = finfo_file($finfo, $filename);
                      finfo_close($finfo);
                      return $mimetype;
                  }
              }
              return 'application/octet-stream';
          }
          return mime_content_type($filename);
      }
      

      // 感谢http://php.net/manual/en/function.mime-content-type.php#107798

      function getMimeTypes()
      {
          $url = 'http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types';
      
          $mimes = array();
          foreach(@explode("\n",@file_get_contents($url)) as $x)
          {
              if(isset($x[0]) && $x[0]!=='#' && preg_match_all('#([^\s]+)#', $x, $out) && isset($out[1]) && ($c = count($out[1])) > 1)
              {
                      for($i=1; $i < $c; $i++)
                  {
                          $mimes[$out[1][$i]] = $out[1][0];
                  }
              }
          }
          return (@sort($mimes)) ? $mimes : false;
      }
      

      使用它链接这个:

      $filename = '/path/to/the/file.pdf';
      $ext = strtolower(array_pop(explode('.',$filename)));
      $content_type = getMimeContentType($filename, $ext);
      

      即使在 php 中不再支持 mime_content_type 函数也会继续工作。

      【讨论】:

        猜你喜欢
        • 2011-04-11
        • 2016-05-19
        • 2011-04-20
        • 2014-01-30
        • 2015-09-13
        • 2018-12-01
        • 2011-11-22
        • 2014-09-28
        相关资源
        最近更新 更多