【问题标题】:Getting mime type of zipped files获取 mime 类型的压缩文件
【发布时间】:2012-05-08 22:38:43
【问题描述】:

获取上传文件的 MIME 类型非常简单:

echo mime_content_type($fileatt['tmp_name']);

但是,我还想检查压缩文件中包含的文件的 mime 类型。解压缩我的文件后(循环浏览 zip 中的文件,i 是当前文件),我试过了:

$info = pathinfo($zip->getNameIndex($i));
echo mime_content_type($info['dirname'] . "\\" . $info['basename']);

这给出了错误:警告:mime_content_type() [function.mime-content-type]: File or path not found '.\foo.pdf' in C:\Users\<user>\<website>\validation.php on line 56

我意识到压缩文件的dirname是相对于压缩文件的,而不是绝对路径,所以我尝试了:

$a = pathinfo($fileatt['tmp_name']);
$b = $a['dirname'] . "\\" . $info['basename'];
echo mime_content_type($b);

给出错误:警告:mime_content_type() [function.mime-content-type]: File or path not found 'C:\xampp\tmp\foo.pdf' in C:\Users\<user>\<website>\validation.php on line 56

任何人都可以对文件的路径有所了解吗? (我怀疑答案可能和getting image height and width from zipped files上的评论一样,但是有没有替代方法?)

更新

感谢 Baba,以下方法确实有效:

$fp = fopen('zip://C:\Users\<user>\<website>\test.zip#foo.jpg', "r");

(n.b. 只有当我给出 zip 文件的完整路径时,我才能让它工作,而不是像通过表单上传文件时那样的 tmp 文件)。但是,尝试获取 mime 类型:echo mime_content_type($fp); 会产生错误:

Warning: mime_content_type() [function.mime-content-type]: stream does not support seeking in C:\Users\<user>\<website>\includes\validation.php on line 70

无论文件类型如何,都会发生这种情况(即http://php.net/manual/en/ziparchive.getstream.php 的唯一评论中所述的问题似乎对我没有影响)。

顺便说一句,这也是我尝试不同方法时遇到的相同错误:$fp = $zip-&gt;getStream('foo.jpg');

我知道在 SO 上还有其他几个“不支持流”的问题,但我无法弄清楚它们与我的问题有何关系,我希望由于这种方法已被特别建议,有人可能会有一个好的回答...

(p.s. 我没有使用 finfo_* 函数,因为我的主机目前拒绝安装 PHP v5.3)。

【问题讨论】:

  • 你用Zip extension's stream wrapper测试过吗?
  • 您只能在物理文件上使用mime_content_type(),这意味着,您必须将文件从 zip 解压缩到某个目录中,然后循环遍历它们,而不仅仅是遍历 zip 中的文件列表.

标签: php


【解决方案1】:

使用上面简单的[你可以说大一个?]函数,你可以提取或获取文件的mime类型或者你可以说内容。

但在使用此功能之前,您可能需要进行一些预配置,

就像你必须确保你在 php.ini 文件中打开或配置了 curl 扩展、文件系统相关扩展和 finfo 扩展。

这里,我简单描述一下这个函数的整个过程。

  1. 首先,我们将所有更新的 mime 类型存储为来自官方 apache mime 类型 url 的数组。

您还可以在 apache conf 目录中获取此 mime 类型文件 安装使用 url。在这个函数中,我们使用 live url 来获取所有的 mime 类型。

  1. 但此函数的第零个过程是验证 apache url 是否有效。

  2. 验证 url 后,如果 url 被验证 [表示 live ],我们将来自该 url 的所有 mime 存储为一个名为 $mimes

    的数组

如果 url 不存在或不存在,我们将手动创建一个具有一些通用扩展名的数组。

  1. 然后我们将内容验证为文件。

  2. 然后我们检查 PHP pathinfo 函数以确保是否有任何文件扩展名。如果有,请将其存储起来。

  3. 之后,我们检查 $mimes 数组和我们的 content extension 作为 $mimes 数组索引。

  4. 最后我们通过$content_mime变量$mimes数组的索引值作为内容mime类型返回.

就是这样。

<?php
    /**
     * **get_content_mime_type
     *
     * @param  string $content, the content or the file whose mime type you want to know.
     * @return string
     */
    function get_content_mime_type($content)
    {
        $url = 'http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types';
        $url_live = false;
        $handle = curl_init($url);
        curl_setopt_array($handle, array(
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_NOBODY => true,
            CURLOPT_HEADER => false,
            CURLOPT_RETURNTRANSFER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_SSL_VERIFYPEER => false
        ));
        $response = curl_exec($handle);
        $httpCode = curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);
        $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
        if ($httpCode == 200)
        {
            $url_live = true;
        }
        $url_live = $url_live;
        curl_close($handle);
        $mimes = array();
        if ($url_live)
        {
            $mimes_file = file_get_contents($url);
            preg_match_all('#^([^\s]{2,}?)\s+(.+?)$#ism', $mimes_file, $matches, PREG_SET_ORDER);
            foreach ($matches as $match)
            {
                $exts = explode(" ", $match[2]);
                foreach ($exts as $ext)
                {
                    $mimes[$ext] = $match[1];
                }
            }
        }
        else
        {
            $mimes = array(
                'txt' => 'text/plain',
                'htm' => 'text/html',
                'html' => 'text/html',
                'php' => 'text/html',
                'css' => 'text/css',
                'js' => 'application/javascript',
                'json' => 'application/json',
                'xml' => 'application/xml',
                'swf' => 'application/x-shockwave-flash',
                'flv' => 'video/x-flv',
                // images
                'png' => 'image/png',
                'jpe' => 'image/jpeg',
                'jpeg' => 'image/jpeg',
                'jpg' => 'image/jpeg',
                'gif' => 'image/gif',
                'bmp' => 'image/bmp',
                'ico' => 'image/vnd.microsoft.icon',
                'tiff' => 'image/tiff',
                'tif' => 'image/tiff',
                'svg' => 'image/svg+xml',
                'svgz' => 'image/svg+xml',
                // archives
                'zip' => 'application/zip',
                'rar' => 'application/x-rar-compressed',
                'exe' => 'application/x-msdownload',
                'msi' => 'application/x-msdownload',
                'cab' => 'application/vnd.ms-cab-compressed',
                // audio/video
                'mp3' => 'audio/mpeg',
                'qt' => 'video/quicktime',
                'mov' => 'video/quicktime',
                // adobe
                'pdf' => 'application/pdf',
                'psd' => 'image/vnd.adobe.photoshop',
                'ai' => 'application/postscript',
                'eps' => 'application/postscript',
                'ps' => 'application/postscript',
                // ms office
                'doc' => 'application/msword',
                'rtf' => 'application/rtf',
                'xls' => 'application/vnd.ms-excel',
                'ppt' => 'application/vnd.ms-powerpoint',
                'docx' => 'application/msword',
                'xlsx' => 'application/vnd.ms-excel',
                'pptx' => 'application/vnd.ms-powerpoint',
                // open office
                'odt' => 'application/vnd.oasis.opendocument.text',
                'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
            );
        }
        $content_mime = 'unknown';
        if (is_file($content))
        {
            if (isset(pathinfo($content) ['extension']))
            {
                $content_ext = pathinfo($content) ['extension'];
                if (isset($mimes[$content_ext]))
                {
                    $content_mime = $mimes[$content_ext];
                }
                else
                {
                    if (is_readable($content) && is_executable($content))
                    {
                        $finfo = finfo_open(FILEINFO_MIME_TYPE);
                        $content_mime = finfo_file($finfo, $content);
                        if ($content_mime === null | $content_mime === "")
                        {
                            $content_mime = "application/octet-stream";
                        }
                        else
                        {
                            $content_mime = $content_mime;
                        }
                        finfo_close($finfo);
                    }
                    else
                    {
                        $content_mime = "application/octet-stream";
                    }
                }
            }
        }
        else
        {
            // return whatever you want
            // $content_mime = 'unknown';
            
        }
        $content_mime = $content_mime;
        return $content_mime;
    }
    ?>

【讨论】:

    【解决方案2】:

    我知道你提到你找不到 php

    很简单,您可以在二进制数据上使用finfo->buffer 来提取 MIME 类型,无需将内容提取到新文件即可使用。

    $fileToUnzip = 0;
    
    $zip = new ZipArchive;
    $zip->open("dir/archive.zip");
    $binary = $zip->getFromIndex($fileToUnzip);
    $filename = $zip->getNameIndex($fileToUnzip);
    $zip->close();
    
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $MIMETypeAndCharset = $finfo->buffer($binary);
    
    // discard charset info
    $MIMETypeAndCharsetArray = explode(';', $MIMETypeAndCharset);
    $MIMEtype = $MIMETypeAndCharsetArray[0];
    
    
    // you can change the source of an iframe to this php file in order to view a preview
    // If the browser can't handle the file, the user is presented with a download box
    
    header('Content-Type:$MIMEtype');
    header('Content-Disposition: inline; filename="July Report.pdf"')
    echo $binary;
    

    【讨论】:

      【解决方案3】:

      A.你可以先试试

       mime_content_type('zip:///path/to/file.zip#'. $chapterZip->getNameIndex ( $i ));
      

      B.我现在只能想到的是 mime_content_type 的替代品,它可能不是最好的方法,但我相信它会浮出水面,直到我找到更好的解决方案

      $chapterZip = new ZipArchive ();
      if ($chapterZip->open ( "stockoverflow.zip" )) {
          for($i = 0; $i < $chapterZip->numFiles; $i ++) {
              var_dump ( mime_content_type_replacement ( $chapterZip->getNameIndex ( $i ) ) );
          }
      }
      

      使用file extensionfinfo_open ( FILEINFO_MIME )的替换函数

      function mime_content_type_replacement($filename) {
      
          $mime_types = array (
      
                  'txt' => 'text/plain',
                  'htm' => 'text/html',
                  'html' => 'text/html',
                  'php' => 'text/html',
                  'css' => 'text/css',
                  'js' => 'application/javascript',
                  'json' => 'application/json',
                  'xml' => 'application/xml',
                  'swf' => 'application/x-shockwave-flash',
                  'flv' => 'video/x-flv',
      
                  // images
                  'png' => 'image/png',
                  'jpe' => 'image/jpeg',
                  'jpeg' => 'image/jpeg',
                  'jpg' => 'image/jpeg',
                  'gif' => 'image/gif',
                  'bmp' => 'image/bmp',
                  'ico' => 'image/vnd.microsoft.icon',
                  'tiff' => 'image/tiff',
                  'tif' => 'image/tiff',
                  'svg' => 'image/svg+xml',
                  'svgz' => 'image/svg+xml',
      
                  // archives
                  'zip' => 'application/zip',
                  'rar' => 'application/x-rar-compressed',
                  'exe' => 'application/x-msdownload',
                  'msi' => 'application/x-msdownload',
                  'cab' => 'application/vnd.ms-cab-compressed',
      
                  // audio/video
                  'mp3' => 'audio/mpeg',
                  'qt' => 'video/quicktime',
                  'mov' => 'video/quicktime',
      
                  // adobe
                  'pdf' => 'application/pdf',
                  'psd' => 'image/vnd.adobe.photoshop',
                  'ai' => 'application/postscript',
                  'eps' => 'application/postscript',
                  'ps' => 'application/postscript',
      
                  // ms office
                  'doc' => 'application/msword',
                  'rtf' => 'application/rtf',
                  'xls' => 'application/vnd.ms-excel',
                  'ppt' => 'application/vnd.ms-powerpoint',
      
                  // open office
                  'odt' => 'application/vnd.oasis.opendocument.text',
                  'ods' => 'application/vnd.oasis.opendocument.spreadsheet' 
          );
      
          $ext = pathinfo ( $filename, PATHINFO_EXTENSION );
          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;
          } else {
              return 'application/octet-stream';
          }
      }
      

      更多的 mime 类型

      PHP / Mime Types - List of mime types publically available?

      http://snipplr.com/view/1937/

      编辑 1

      刚刚测试了以下,它可以工作

      $fp = fopen('zip://C:\stockoverflow.zip#1.MOV.xml',"r");
      

      编辑 2

      A. mime_content_type($fp) 不起作用,因为 mime_content_type 只接受字符串参数,请参阅 http://php.net/manual/en/function.mime-content-type.php

      B.不知道为什么你还坚持mime_content_type,因为它也已经贬值了

      此功能已被弃用,因为 PECL 扩展 Fileinfo 以更简洁的方式提供了相同的功能(以及更多功能)。

      C.直接在$fileatt['tmp_name'] 上工作并不理想.. 它是一个临时文件,不能被操纵.. 要处理该文件,您需要将其复制到您的 PHP 将拥有访问它的完全权限的服务器

      D. ZipArchive::getStream 仅适用于 zip 文件的本地副本,而不适用于临时上传文件

      【讨论】:

      • 感谢您的建议。我不确定出了什么问题:我有 $fp = fopen('zip:\\\\\\'.$a['dirname'].'\\test.zip#file.pdf', 'r');(由于 Windows 的反斜杠,它们都需要转义 - 我认为这是正确的?),$a 与我的问题中定义的相同;但我得到了错误:Warning: fopen(zip:\\\C:\xampp\tmp\test.zip#file.pdf) [function.fopen]: failed to open stream: Invalid argument in C:\Users\&lt;user&gt;\&lt;website&gt;\includes\validation.php on line 60
      • $fp = fopen('zip://C:\stockoverflow.zip#1.MOV.xml',"r"); 工作
      • 感谢您迄今为止提供的帮助;我在我的问题中提供了更多信息 - 如果您有更多建议,我很乐意尝试:)
      • 我认为总体答案是,如果不保存 zip 1st,就不可能做我想做的事。 PECL 扩展仅包含在 PHP 5.3+ 中(我的主机不会安装 - 显然它破坏了太多东西......)。如果finfo_* 方法被贬值,我应该改用什么?
      猜你喜欢
      • 2015-11-01
      • 2018-12-01
      • 1970-01-01
      • 2014-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-30
      • 2015-09-13
      相关资源
      最近更新 更多