【问题标题】:How to get the mime type of a file after using file_get_contents from a remote server从远程服务器使用 file_get_contents 后如何获取文件的 mime 类型
【发布时间】:2011-06-07 23:38:55
【问题描述】:

我正在从 Alfresco 读取 PHP 文件,然后将其输出到浏览器。唯一的问题是文件的 MIME 类型或扩展名。这是我正在使用的代码:

<?php
ob_start();
require_once("libs/AlfrescoConnect.php");

$nomeFile = rawurldecode($_GET['nomeFile']);    
$urlDownload = $_GET['urlDownload'];
$fileDownloadUrl =
    AlfrescoConnect::$serverPath. $urlDownload .
    "&attach=true&alf_ticket=".AlfrescoConnect::getTiket();
fb($fileDownloadUrl);

$cnt = file_get_contents($fileDownloadUrl);

header("Content-type: Application/octet-stream");
header('Cache-Control: must-revalidate');
header('Content-disposition: attachment; filename=' .$nomeFile);
echo($cnt);
exit();

echo("Impossibile trovare il file");

我从 get 中收到文件的名称,因为我不知道如何从 alfresco 中获取名称。但我必须以某种方式猜测 mimetype。如果我在第一个字符中echo $cnt,则说明它是 PDF 的事实(例如在我看到的屏幕上

%PDF-1.3 %âãÏÓ 2 0 obj > /Type /XObject /Subtype /Image /Width 2480 /高度 3508 /BitsPerComponent 1 /ColorSpace /DeviceGray >> 流

所以必须有一种方法可以通过函数从中获取 mime 类型。

感谢任何帮助!

编辑。如果有人对这里感兴趣,可以使用一个类来从 mime 类型中获取扩展名。 http://www.ustrem.org/en/articles/mime-type-by-extension-en/

【问题讨论】:

    标签: php alfresco mime-types file-get-contents


    【解决方案1】:

    您可以使用finfo::buffer() 方法:http://php.net/finfo_buffer

    <?php
    $finfo = new finfo(FILEINFO_MIME);
    echo $finfo->buffer($cnt) . PHP_EOL;
    

    注意:您可以选择使用 finfo_buffer 过程函数,如果它比使用面向对象的方法更适合您的话。

    【讨论】:

    • 如果使用了file_get_contents,这似乎是正确的方法。
    【解决方案2】:

    您不必猜测(也称为自动检测)MIME 类型。

    使用$http_response_header 检索最后一次file_get_contents 调用(或任何使用http[s]:// wrapper 的调用)的标头。

    $contents = file_get_contents("https://www.example.com/");
    $pattern = "/^content-type\s*:\s*(.*)$/i";
    if (($header = array_values(preg_grep($pattern, $http_response_header))) &&
        (preg_match($pattern, $header[0], $match) !== false))
    {
        $content_type = $match[1];
        echo "Content-Type is '$content_type'\n";
    }
    

    【讨论】:

      【解决方案3】:

      file_get_contents 之后解析$http_response_header 对我来说非常不稳定。在某些情况下,由于请求数量非常多,我无法在标头中找到“Content-Type”。但他们在那里。

      所以,我使用这样的解决方案:

      $content = file_get_contents($url);
      $fh = fopen('php://memory', 'w+b');
      fwrite($fh, $content);
      
      $contentType = mime_content_type($fh);
      
      fclose($fh);
      

      【讨论】:

        【解决方案4】:

        把它放在一个类中:

        /**
         * Given a string ($data) with a file's contents, guess and return the mime type
         *
         * Uses the standard unix program /usr/bin/file to handle the magic (pun intended)
         *
         * @param string $data
         */
        public static function get_string_mime_type($data) {
            $file_cmd = '/usr/bin/file --brief --mime-type --no-buffer -';
            return rtrim(self::exec_write_read($file_cmd, $data));
        }
        
        /**
         * Executes $cmd, writes to $cmd's stdin, then returns what $cmd wrote to stdout
         */
        private static function exec_write_read($cmd, $write, $log_errors = false) {
            $descriptorspec = array(
                0 => array("pipe", "r"),  // stdin is a pipe that $cmd will read from
                1 => array("pipe", "w"),  // stdout is a pipe that $cmd will write to
                2 => array("pipe", "w"),  // stderr is a pipe that $cmd will write to
            );
        
            $process = proc_open($cmd, $descriptorspec, $pipes);
            if (is_resource($process)) {
                // $pipes now looks like this:
                // 0 => writeable handle connected to child stdin
                // 1 => readable handle connected to child stdout
                // 2 => readable handle connected to child stderr
        
                fwrite($pipes[0], $write);
                fclose($pipes[0]);
        
                $output = stream_get_contents($pipes[1]);
                fclose($pipes[1]);
        
                if( $log_errors ){
                    error_log(stream_get_contents($pipes[2]));
                }
                fclose($pipes[2]);
        
                // It is important that you close any pipes before calling
                // proc_close in order to avoid a deadlock
                $exit_code = proc_close($process);
        
                return $output;
            }
            else {
                throw new Exception("Couldn't open $cmd");
            }
        }
        

        【讨论】:

          【解决方案5】:

          使用 cURL 代替 file_get_contents,然后您可以看到响应标头,它有望具有 mime 类型。

          或者您可以尝试使用这个http://www.php.net/manual/en/ref.fileinfo.php 或这个已弃用的函数http://php.net/manual/en/function.mime-content-type.php

          【讨论】:

          • 这假定远程服务器正在发送正确的 mime 类型。它可以只使用 application/octet-stream 来处理所有事情。
          • 在这种情况下它有效!这是我添加的代码: $ch = curl_init($fileDownloadUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_exec($ch); $mime = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
          • HTTP 响应中的 Mime 类型可能不正确,而 mime_content_type() 可以信任并且不会像您所说的那样被弃用。
          【解决方案6】:

          这是 Drupal 中 filefield_sources 模块的 curl 实现。它可能在任何地方都可以工作:

          <?php
            // Inspect the remote image
            // Check the headers to make sure it exists and is within the allowed size.
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_HEADER, TRUE);
            curl_setopt($ch, CURLOPT_NOBODY, TRUE);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($ch, CURLOPT_HEADERFUNCTION, '_filefield_source_remote_parse_header');
            // Causes a warning if PHP safe mode is on.
            @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
            curl_exec($ch);
            $info = curl_getinfo($ch);
            curl_close($ch);
          
          /**
           * Parse cURL header and record the filename specified in Content-Disposition.
           */
          function _filefield_source_remote_parse_header(&$ch, $header) {
            if (preg_match('/Content-Disposition:.*?filename="(.+?)"/', $header, $matches)) {
              // Content-Disposition: attachment; filename="FILE NAME HERE"
              _filefield_source_remote_filename($matches[1]);
            }
            elseif (preg_match('/Content-Disposition:.*?filename=([^; ]+)/', $header, $matches)) {
              // Content-Disposition: attachment; filename=file.ext
              _filefield_source_remote_filename($matches[1]);
            }
          
            // This is required by cURL.
            return strlen($header);
          }
          
          /**
           * Get/set the remote file name in a static variable.
           */
          function _filefield_source_remote_filename($curl_filename = NULL) {
            static $filename = NULL;
            if (isset($curl_filename)) {
              $filename = $curl_filename;
            }
            return $filename;
          }
          
           ?>
          

          要获得哑剧:

          <?php
          echo $info['content_type'];
          ?>
          

          代码在这里:http://drupal.org/project/filefield_sources

          【讨论】:

            【解决方案7】:

            小心!不仅要检查 mimetype,还要检查恶意代码!!!!!!!!!

            详情:PHP: How to get mimeType of a image with file_get_contents

            【讨论】:

              猜你喜欢
              • 2014-02-13
              • 1970-01-01
              • 2014-10-03
              • 2015-10-31
              • 1970-01-01
              • 1970-01-01
              • 2021-06-27
              • 2011-04-17
              • 1970-01-01
              相关资源
              最近更新 更多