正确的方法来检测php中的mime类型 [英] Correct way to detect mime type in php

查看:110
本文介绍了正确的方法来检测php中的mime类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在php中检测文件的mime类型的最佳和可靠方法是什么? 许多人建议的以下代码未能检测到docx文件的mime类型:

What is the best and reliable way to detect mime type of a file in php? The following code which is suggested by many people failed to detect docx file mime type:

 $finfo = new finfo(FILEINFO_MIME_TYPE);
 $mime = $finfo->file($_FILES['file']['tmp_name']); 
 echo $mime; exit;  

这正在打印 application/zip ,但应该是

application/vnd.openxmlformats-officedocument.wordprocessingml.document

推荐答案

基于

Based on this I've ported it to PHP:

function getMicrosoftOfficeMimeInfo($file) {
    $fileInfo = array(
        'word/' => array(
            'type'      => 'Microsoft Word 2007+',
            'mime'      => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'extension' => 'docx'
        ),
        'ppt/' => array(
            'type'      => 'Microsoft PowerPoint 2007+',
            'mime'      => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'extension' => 'pptx'
        ),
        'xl/' => array(
            'type'      => 'Microsoft Excel 2007+',
            'mime'      => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'extension' => 'xlsx'
        )
    );

    $pkEscapeSequence = "PK\x03\x04";

    $file = new BinaryFile($file);
    if ($file->bytesAre($pkEscapeSequence, 0x00)) {
        if ($file->bytesAre('[Content_Types].xml', 0x1E)) {
            if ($file->search($pkEscapeSequence, null, 2000)) {
                if ($file->search($pkEscapeSequence, null, 1000)) {
                    $offset = $file->tell() + 26;
                    foreach ($fileInfo as $searchWord => $info) {
                        $file->seek($offset);
                        if ($file->bytesAre($searchWord)) {
                            return $fileInfo[$searchWord];
                        }
                    }
                    return array(
                        'type'      => 'Microsoft OOXML',
                        'mime'      => null,
                        'extension' => null
                    );
                }
            }
        }
    }

    return false;
}

class BinaryFile_Exception extends Exception {}

class BinaryFile_Seek_Method {
    const ABSOLUTE = 1;
    const RELATIVE = 2;
}

class BinaryFile {
    const SEARCH_BUFFER_SIZE = 1024;

    private $handle;

    public function __construct($file) {
        $this->handle = fopen($file, 'r');
        if ($this->handle === false) {
            throw new BinaryFile_Exception('Cannot open file');
        }
    }

    public function __destruct() {
        fclose($this->handle);
    }

    public function tell() {
        return ftell($this->handle);
    }

    public function seek($offset, $seekMethod = null) {
        if ($offset !== null) {
            if ($seekMethod === null) {
                $seekMethod = BinaryFile_Seek_Method::ABSOLUTE;
            }
            if ($seekMethod === BinaryFile_Seek_Method::RELATIVE) {
                $offset += $this->tell();
            }
            return fseek($this->handle, $offset);
        } else {
            return true;
        }
    }

    public function read($length) {
        return fread($this->handle, $length);
    }

    public function search($string, $offset = null, $maxLength = null, $seekMethod = null) {
        if ($offset !== null) {
            $this->seek($offset);
        } else {
            $offset = $this->tell();
        }

        $bytesRead = 0;
        $bufferSize = ($maxLength !== null ? min(self::SEARCH_BUFFER_SIZE, $maxLength) : self::SEARCH_BUFFER_SIZE);

        while ($read = $this->read($bufferSize)) {
            $bytesRead += strlen($read);
            $search = strpos($read, $string);

            if ($search !== false) {
                $this->seek($offset + $search + strlen($string));
                return true;
            }

            if ($maxLength !== null) {
                $bufferSize = min(self::SEARCH_BUFFER_SIZE, $maxLength - $bytesRead);
                if ($bufferSize == 0) {
                    break;
                }
            }
        }
        return false;
    }

    public function getBytes($length, $offset = null, $seekMethod = null) {
        $this->seek($offset, $seekMethod);
        $read = $this->read($length);
        return $read;
    }

    public function bytesAre($string, $offset = null, $seekMethod = null) {
        return ($this->getBytes(strlen($string), $offset) == $string);
    }
}

用法:

$info = getMicrosoftOfficeMimeInfo('hi.docx');
/*
    Array
    (
        [type] => Microsoft Word 2007+
        [mime] => application/vnd.openxmlformats-officedocument.wordprocessingml.document
        [extension] => docx
    )
*/

$info = getMicrosoftOfficeMimeInfo('hi.xlsx');
/*
    Array
    (
        [type] => Microsoft Excel 2007+
        [mime] => application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        [extension] => xlsx
    )
*/

$info = getMicrosoftOfficeMimeInfo('hi.pptx');
/*
    Array
    (
        [type] => Microsoft PowerPoint 2007+
        [mime] => application/vnd.openxmlformats-officedocument.presentationml.presentation
        [extension] => pptx
    )
*/

$info = getMicrosoftOfficeMimeInfo('hi.zip');
// bool(false)

这篇关于正确的方法来检测php中的mime类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆