PHP根据文件头检测文件类型

文件签名一般都在文件的头部,如果你用十六进制方式查看文件,你就可以看到文件的一些签名信息。如用uestudio以十六进制方式查看zip格式的文件,其文件内容头部有50 4B 03 04这样的十六进制信息。同理jpg文件状况有FF D8 FF E0 xx xx 4A 46这样的十六进制信息,其实这此十六进制都是表示一些特殊字条。

php怎么样验证文件类型?先来看一个简单的方法:
01    function checkFileType($fileName){ 
02        $file = fopen($fileName, "rb"); 
03        $bin = fread($file, 2); //只读2字节 
04        fclose($file); 
05        // C为无符号整数,网上搜到的都是c,为有符号整数,这样会产生负数判断不正常
06        $strInfo  = @unpack("C2chars", $bin);
07        $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); 
08        $fileType = ''; 
09     
10        switch( $typeCode )
11        {
12            case '255216':
13                return $typeCode. ' : ' .'jpg';
14                break;
15            case '7173':
16                return $typeCode. ' : ' .'gif';
17                break;
18            case '13780':
19                return $typeCode. ' : ' .'png';
20                break;
21            case '6677':
22                return $typeCode. ' : ' .'bmp';
23                break;
24            case '7790':
25                return $typeCode. ' : ' .'exe';
26                break;
27            case '7784':
28                return $typeCode. ' : ' .'midi';
29                break;
30            case '8297':
31                return $typeCode. ' : ' .'rar';
32                break;
33            default:
34                return $typeCode. ' : ' .'Unknown';
35                break;
36        }
37        //return $typeCode;
38    }
39     
40    $file_name = '11.doc';
41    echo checkFileType($file_name);

下来提供一个类的实现:
01    /*通过文件名,获得文件类型*
02     *@author chengmo QQ:8292669*
03     *@copyright <a href="http://www.cnblogs.com/chengmo">http://www.cnblogs.com/chengmo</a> 2010-10-17
04     *@version 0.1
05     *$filename="d:/1.png";echo cFileTypeCheck::getFileType($filename); 打印:png
06     */
07    class cFileTypeCheck
08    {
09        private static $_TypeList=array();
10        private static $CheckClass=null;
11        private function __construct($filename)
12        {
13            self::$_TypeList=$this->getTypeList();
14        }
15      
16        /**
17         *处理文件类型映射关系表*
18         *
19         * @param string $filename 文件类型
20         * @return string 文件类型,没有找到返回:other
21         */
22        private function _getFileType($filename)
23        {
24            $filetype="other";
25            if(!file_exists($filename)) throw new Exception("no found file!");
26            $file = @fopen($filename,"rb");
27            if(!$file) throw new Exception("file refuse!");
28            $bin = fread($file, 15); //只读15字节 各个不同文件类型,头信息不一样。
29            fclose($file);
30              
31            $typelist=self::$_TypeList;
32            foreach ($typelist as $v)
33            {
34                $blen=strlen(pack("H*",$v[0])); //得到文件头标记字节数
35                $tbin=substr($bin,0,intval($blen)); ///需要比较文件头长度
36                  
37                if(strtolower($v[0])==strtolower(array_shift(unpack("H*",$tbin))))
38                {
39                    return $v[1];
40                }
41            }
42            return $filetype;
43        }
44          
45        /**
46         *得到文件头与文件类型映射表*
47         *
48         * @return array array(array('key',value)...)
49         */
50        public function getTypeList()
51        {
52            return array(array("FFD8FFE1","jpg"),
53            array("89504E47","png"),
54            array("47494638","gif"),
55            array("49492A00","tif"),
56            array("424D","bmp"),
57            array("41433130","dwg"),
58            array("38425053","psd"),
59            array("7B5C727466","rtf"),
60            array("3C3F786D6C","xml"),
61            array("68746D6C3E","html"),
62            array("44656C69766572792D646174","eml"),
63            array("CFAD12FEC5FD746F","dbx"),
64            array("2142444E","pst"),
65            array("D0CF11E0","xls/doc"),
66            array("5374616E64617264204A","mdb"),
67            array("FF575043","wpd"),
68            array("252150532D41646F6265","eps/ps"),
69            array("255044462D312E","pdf"),
70            array("E3828596","pwl"),
71            array("504B0304","zip"),
72            array("52617221","rar"),
73            array("57415645","wav"),
74            array("41564920","avi"),
75            array("2E7261FD","ram"),
76            array("2E524D46","rm"),
77            array("000001BA","mpg"),
78            array("000001B3","mpg"),
79            array("6D6F6F76","mov"),
80            array("3026B2758E66CF11","asf"),
81            array("4D546864","mid"));
82        }
83      
84         
85        public static function getFileType($filename)
86        {
87            if(!self::$CheckClass) self::$CheckClass=new self($filename);
88            $class=self::$CheckClass;
89            return $class->_getFileType($filename);
90        }
91         
92    }
93     
94    $filename="22.jpg";
95    echo $filename,"t",cFileTypeCheck::getFileType($filename),"rn";
96    $filename="11.doc";
97    echo $filename,"t",cFileTypeCheck::getFileType($filename),"rn";

或者可以这么检测:
01    $filename = '22.jpg';
02      
03    $extname = strtolower(substr($filename, strrpos($filename, '.') + 1));
04    echo $extname.'<br />';
05    $file = @fopen($filename, 'rb');
06        if ($file)
07        {
08            $str = @fread($file, 0x400); // 读取前 1024 个字节
09            echo substr($str, 0, 4);
10            @fclose($file);
11        }
12        if (substr($str, 0, 4) == 'MThd' && $extname != 'txt')
13            {
14                $format = 'mid';
15            }
16            elseif (substr($str, 0, 4) == 'RIFF' && $extname == 'wav')
17            {
18                $format = 'wav';
19            }
20            elseif (substr($str ,0, 3) == "/xFF/xD8/xFF")
21            {
22                $format = 'jpg';
23            }
24            elseif (substr($str ,0, 4) == 'GIF8' && $extname != 'txt')
25            {
26                $format = 'gif';
27            }
28            elseif (substr($str ,0, 8 ) == "/x89/x50/x4E/x47/x0D/x0A/x1A/x0A")
29            {
30                $format = 'png';
31            }
32            elseif (substr($str ,0, 2) == 'BM' && $extname != 'txt')
33            {
34                $format = 'bmp';
35            }
36            elseif ((substr($str ,0, 3) == 'CWS' || substr($str ,0, 3) == 'FWS') && $extname != 'txt')
37            {
38                $format = 'swf';
39            }
40            elseif (substr($str ,0, 4) == "/xD0/xCF/x11/xE0")
41            {   // D0CF11E == DOCFILE == Microsoft Office Document
42                if (substr($str,0x200,4) == "/xEC/xA5/xC1/x00" || $extname == 'doc')
43                {
44                    $format = 'doc';
45                }
46                elseif (substr($str,0x200,2) == "/x09/x08" || $extname == 'xls')
47                {
48                    $format = 'xls';
49                } elseif (substr($str,0x200,4) == "/xFD/xFF/xFF/xFF" || $extname == 'ppt')
50                {
51                    $format = 'ppt';
52                }
53            } elseif (substr($str ,0, 4) == "PK/x03/x04")
54            {
55                $format = 'zip';
56            } elseif (substr($str ,0, 4) == 'Rar!' && $extname != 'txt')
57            {
58                $format = 'rar';
59            } elseif (substr($str ,0, 4) == "/x25PDF")
60            {
61                $format = 'pdf';
62            } elseif (substr($str ,0, 3) == "/x30/x82/x0A")
63            {
64                $format = 'cert';
65            } elseif (substr($str ,0, 4) == 'ITSF' && $extname != 'txt')
66            {
67                $format = 'chm';
68            } elseif (substr($str ,0, 4) == "/x2ERMF")
69            {
70                $format = 'rm';
71            } elseif ($extname == 'sql')
72            {
73                $format = 'sql';
74            } elseif ($extname == 'txt')
75            {
76                $format = 'txt';
77            }
78             
79            echo $format;
原文地址:https://www.cnblogs.com/afei-happy/p/3376432.html