强大的php检查文件类型

 更新时间:2016年11月25日 17:40  点击:2065
一个强大的文件类型检测函数,它可以判断你上传的文件是什么类型,这个你没有办法为装过去的,有需要的朋友可以参考一下。
 代码如下 复制代码
**
 *
 *
 * @access      public
 * @param       string      filename            文件名
 * @param       string      limit_ext_types     允许的文件类型,用|包围的类型如:|gif|txt|
 * @return      string
 */<span id="more-472"></span>
function check_file_type($filename, $limit_ext_types = ''){
 $extname = strtolower(substr($filename, strrpos($filename, '.') + 1));
 if ($limit_ext_types &&
 stristr($limit_ext_types, '|' . $extname . '|') === false){
  return '';
 }
 
 $str = $format = '';
 
 $file = @fopen($filename, 'rb');
 if ($file){
  $str = @fread($file, 0x400); // 读取前 1024 个字节
  @fclose($file);
 }
 else{
  $format=$extname;
 }
 
 if ($format == '' && strlen($str) >= 2 ){
  if (substr($str, 0, 4) == 'MThd' && $extname != 'txt'){
   $format = 'mid';
  }
  elseif (substr($str, 0, 4) == 'RIFF' && $extname == 'wav'){
   $format = 'wav';
  }
  elseif (substr($str ,0, 3) == "xFFxD8xFF"){
   $format = 'jpg';
  }
  elseif (substr($str ,0, 4) == 'GIF8' && $extname != 'txt'){
   $format = 'gif';
  }
  elseif (substr($str ,0, 8) == "x89x50x4Ex47x0Dx0Ax1Ax0A"){
   $format = 'png';
  }
  elseif (substr($str ,0, 2) == 'BM' && $extname != 'txt'){
   $format = 'bmp';
  }
  elseif ((substr($str ,0, 3) == 'CWS' || substr($str ,0, 3) == 'FWS')
  && $extname != 'txt'){
   $format = 'swf';
  }
  elseif (substr($str ,0, 4) == "xD0xCFx11xE0"){   // D0CF11E == DOCFILE == Microsoft Office Document
   if (substr($str,0x200,4) == "xECxA5xC1x00"
   || $extname == 'doc'){
    $format = 'doc';
   }
   elseif (substr($str,0x200,2) == "x09x08" || $extname == 'xls'){
    $format = 'xls';
   }
   elseif (substr($str,0x200,4) == "xFDxFFxFFxFF"
   || $extname == 'ppt'){
    $format = 'ppt';
   }
  }
  elseif (substr($str ,0, 4) == "PKx03x04"){
   $format = 'zip';
  }
  elseif (substr($str ,0, 4) == 'Rar!' && $extname != 'txt'){
   $format = 'rar';
  }
  elseif (substr($str ,0, 4) == "x25PDF"){
   $format = 'pdf';
  }
  elseif (substr($str ,0, 3) == "x30x82x0A"){
   $format = 'cert';
  }
  elseif (substr($str ,0, 4) == 'ITSF' && $extname != 'txt'){
   $format = 'chm';
  }
  elseif (substr($str ,0, 4) == "x2ERMF"){
   $format = 'rm';
  }
  elseif ($extname == 'sql'){
   $format = 'sql';
  }
  elseif ($extname == 'txt'){
   $format = 'txt';
  }
 }
 
 if ($limit_ext_types &&
 stristr($limit_ext_types, '|' . $format . '|') === false){
  $format = '';
 }
 
 return $format;
}
 
本函数算是强大了,比起php自带的函数强大多了,此函数可以自动获取你给的字符编码,然后根据你的参考转换成你想要的编码,有需要的朋友可以参考一下。
 代码如下 复制代码
/**
 * 循环实现编码互转
 *
 * @param string $param(字符串,对象,或者数组),$currCharset当前编码,$toCharset期望编码
 * @return 参数类型
 */
function zhandi_iconv($param,$currCharset,$toCharset){
 if ($currCharset != $toCharset){
  if (is_string($param)){
   return iconv($currCharset, $toCharset, $param);
  }
  elseif (is_array($param)){
   foreach ($param as $key => $value){
    $param[$key] = zhandi_iconv($value);
   }
   return $param;
  }
  elseif (is_object($param)){
   foreach ($param as $key => $value){
    $param->$key = zhandi_iconv($value);
   }
   return $param;
  }
  else{
   return $param;
  }
 }
 return $param;
}
很久没写php了今天在用时突然了其怪的乱码错误重现是我惊诧莫名啊!,下面来看看我的排查方法,给碰到相同问题的朋友一个参考。

有一个很久的工程今天要莫名其妙的重新启动了,这个工程是xampp的环境——不知道xampp?你Google一下吧,这个我不多说了。

一开始轻车熟路,apahce配置,php配置……一路下来没有任何问题。开始访问吧,问题就来了,很奇怪预料之中可以运行的页面,却出了个预料之外的乱码问题。

第一个想到的是,apache的缺省字符集,于是在apache的语言扩展配置文件中加入:

AddDefaultCharset UTF-8

我的网站页面是utf-8的哦,重新启动并没有预想之中的起到作用——也就是没有作用啦!多方努力都没有作用,就这样在httpd.conf上浪费了半个小时。开始郁闷……

半个小时过去了,抽了一支烟,想到phpinfo可能能够帮上忙哦,于是打开phpinfo一看,立即惊呆了。在HTTP Response Headers一栏下的 Content-Type 项中赫然出现了:text/html gbk字样,我神呢——,为啥是gbk呢。于是重新查找各项设置,httpd.conf没有,各项扩展里面都没有这个gbk的东东……

郁闷中……

php.ini,这是总算找到了,不知道哪个鸟人狂贱的把这个地方的设置打开了,并且还不是正确的,哪个地方?

default_charset = “gbk”

就这个地方,害死老子哦!于是修改成:
default_charset = “UTF-8″

重启,一切正常了!但是咱们也不能害人不是,想着去掉看看可以不,去掉之后一切还是正常的——页面显示编码控制权重新回到了页面本身。

 

因为用到一个简单的功能,我们用到了file_get_contents 函数,这样它把CPU 100%经过分析确实了是它景起了,现在我们来看看引起cpu 100%的解决办法吧。

运行 Nginx、PHP-CGI(php-fpm) Web服务的 Linux 服务器,突然系统负载上升,使用 top 命令查看,很多 php-cgi 进程 CPU 使用率接近100%。后来,我通过跟踪发现,这类情况的出现,跟 PHP 的 file_get_contents() 函数有着密切的关系。

大、中型网站中,基于 HTTP 协议的 API 接口调用,是家常便饭。PHP 程序员们喜欢使用简单便捷的 file_get_contents(“http://example.com/”) 函数,来获取一个 URL 的返回内容,但是,如果 http://example.com/ 这个网站响应缓慢,file_get_contents() 就会一直卡在那儿,不会超时。

我们知道,在 php.ini 中,有一个参数 max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效。真正能够控制 PHP 脚本最大执行时间的是 php-fpm.conf 配置文件中的以下参数:

The timeout (in seconds) for serving a single request after which the worker process will be terminated
Should be used when ‘max_execution_time’ ini option does not stop script execution for some reason
’0s’ means ‘off’
<value name=”request_terminate_timeout”>0s</value>


默认值为 0 秒,也就是说,PHP 脚本会一直执行下去。这样,当所有的 php-cgi 进程都卡在 file_get_contents() 函数时,这台 Nginx+PHP 的 WebServer 已经无法再处理新的 PHP 请求了,Nginx 将给用户返回“502 Bad Gateway”。修改该参数,设置一个 PHP 脚本最大执行时间是必要的,但是,治标不治本。例如改成 30s,如果发生 file_get_contents() 获取网页内容较慢的情况,这就意味着 150 个 php-cgi 进程,每秒钟只能处理 5 个请求,WebServer 同样很难避免“502 Bad Gateway”。

要做到彻底解决,只能让 PHP 程序员们改掉直接使用 file_get_contents(“http://example.com/”) 的习惯,而是稍微修改一下,加个超时时间,用以下方式来实现 HTTP GET 请求。要是觉得麻烦,可以自行将以下代码封装成一个函数。

 代码如下 复制代码

<?php
$ctx = stream_context_create(array(
‘http’ => array(
‘timeout’ => 1 //设置一个超时时间,单位为秒
)
)
);
file_get_contents(“http://example.com/“, 0, $ctx);
?>

 

当然,导致 php-cgi 进程 CPU 100% 的原因不只有这一种,那么,怎么确定是 file_get_contents() 函数导致的呢?

首先,使用 top 命令查看 CPU 使用率较高的 php-cgi 进程。

top – 10:34:18 up 724 days, 21:01,  3 users,  load average: 17.86, 11.16, 7.69
Tasks: 561 total,  15 running, 546 sleeping,   0 stopped,   0 zombie
Cpu(s):  5.9%us,  4.2%sy,  0.0%ni, 89.4%id,  0.2%wa,  0.0%hi,  0.2%si,  0.0%st
Mem:   8100996k total,  4320108k used,  3780888k free,   772572k buffers
Swap:  8193108k total,    50776k used,  8142332k free,   412088k cachedPID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
10747 www       18   0  360m  22m  12m R 100.6 0.3    0:02.60 php-cgi
10709 www       16   0  359m  28m  17m R 96.8  0.4    0:11.34 php-cgi
10745 www       18   0  360m  24m  14m R 94.8  0.3    0:39.51 php-cgi
10707 www       18   0  360m  25m  14m S 77.4  0.3    0:33.48 php-cgi
10782 www       20   0  360m  26m  15m R 75.5  0.3    0:10.93 php-cgi
10708 www       25   0  360m  22m  12m R 69.7  0.3    0:45.16 php-cgi
10683 www       25   0  362m  28m  15m R 54.2  0.4    0:32.65 php-cgi
10711 www       25   0  360m  25m  15m R 52.2  0.3    0:44.25 php-cgi
10688 www       25   0  359m  25m  15m R 38.7  0.3    0:10.44 php-cgi
10719 www       25   0  360m  26m  16m R  7.7  0.3    0:40.59 php-cgi

 

找其中一个 CPU 100% 的 php-cgi 进程的 PID,用以下命令跟踪一下:

strace -p 10747
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)
select(7, [6], [6], [], {15, 0})        = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (Timeout)

 

那么,就可以确定是 file_get_contents() 导致的问题了。

 

PHP的 strtr 函数, 性能要比 str_replace 函数高, 可以代替 str_replace 来使用. strtr 有两种形式:

 


string strtr ( string $str , string $from , string $to )
string strtr ( string $str , array $replace_pairs )
当使用第一种的时候, 参数 $from, $to 的字符串长度一定要相同, 否则多余的(不管是$from多还是$to多) 字符被忽略.


比如 $str = 'a-=b' ;


当$from='-=' ,$to='CD',输出'aCDb', 因为'-='与'CD'的长度相同,没有问题.


当$from='-=' ,$to='CDE',输出'aCDb', $to里的'E'被忽略.

当$from='-=' ,$to='C',输出'aC=b', $from里的'='被忽略.

而使用第二种形式, 则没有这个问题, 多余的字条不会忽略.


所以,如果故意用 strtr 函数代替 str_replace, 并且使用了第一种形式, 则一定要注意这个特征, 这可能是一个陷阱.

[!--infotagslink--]

相关文章

  • php读取zip文件(删除文件,提取文件,增加文件)实例

    下面小编来给大家演示几个php操作zip文件的实例,我们可以读取zip包中指定文件与删除zip包中指定文件,下面来给大这介绍一下。 从zip压缩文件中提取文件 代...2016-11-25
  • Jupyter Notebook读取csv文件出现的问题及解决

    这篇文章主要介绍了JupyterNotebook读取csv文件出现的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2023-01-06
  • php中浮点型(float)和整型(integer)数据类型详解

    文章分析了关于php中浮点型(float)和整型(integer)数据类型的用法区别以及在那种情况下会出现数据长度不够。 取值只能为True或者False,当其他类型转化为boolean类...2016-11-25
  • Photoshop打开PSD文件空白怎么解决

    有时我们接受或下载到的PSD文件打开是空白的,那么我们要如何来解决这个 问题了,下面一聚教程小伙伴就为各位介绍Photoshop打开PSD文件空白解决办法。 1、如我们打开...2016-09-14
  • C#操作本地文件及保存文件到数据库的基本方法总结

    C#使用System.IO中的文件操作方法在Windows系统中处理本地文件相当顺手,这里我们还总结了在Oracle中保存文件的方法,嗯,接下来就来看看整理的C#操作本地文件及保存文件到数据库的基本方法总结...2020-06-25
  • 解决python 使用openpyxl读写大文件的坑

    这篇文章主要介绍了解决python 使用openpyxl读写大文件的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-13
  • C#实现HTTP下载文件的方法

    这篇文章主要介绍了C#实现HTTP下载文件的方法,包括了HTTP通信的创建、本地文件的写入等,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • c# 数据类型占用的字节数介绍

    本篇文章主要是对c#中数据类型占用的字节数进行了详细的介绍。需要的朋友可以过来参考下,希望对大家有所帮助...2020-06-25
  • SpringBoot实现excel文件生成和下载

    这篇文章主要为大家详细介绍了SpringBoot实现excel文件生成和下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-09
  • Javascript类型转换的规则实例解析

    这篇文章主要介绍了Javascript类型转换的规则实例解析,涉及到javascript类型转换相关知识,对本文感兴趣的朋友一起学习吧...2016-02-27
  • php无刷新利用iframe实现页面无刷新上传文件(1/2)

    利用form表单的target属性和iframe 一、上传文件的一个php教程方法。 该方法接受一个$file参数,该参数为从客户端获取的$_files变量,返回重新命名后的文件名,如果上传失...2016-11-25
  • php批量替换内容或指定目录下所有文件内容

    要替换字符串中的内容我们只要利用php相关函数,如strstr,str_replace,正则表达式了,那么我们要替换目录所有文件的内容就需要先遍历目录再打开文件再利用上面讲的函数替...2016-11-25
  • PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来...2016-11-25
  • AI源文件转photoshop图像变模糊问题解决教程

    今天小编在这里就来给photoshop的这一款软件的使用者们来说下AI源文件转photoshop图像变模糊问题的解决教程,各位想知道具体解决方法的使用者们,那么下面就快来跟着小编...2016-09-14
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • Zend studio文件注释模板设置方法

    步骤:Window -> PHP -> Editor -> Templates,这里可以设置(增、删、改、导入等)管理你的模板。新建文件注释、函数注释、代码块等模板的实例新建模板,分别输入Name、Description、Patterna)文件注释Name: 3cfileDescriptio...2013-10-04
  • php文件上传你必须知道的几点

    本篇文章主要说明的是与php文件上传的相关配置的知识点。PHP文件上传功能配置主要涉及php.ini配置文件中的upload_tmp_dir、upload_max_filesize、post_max_size等选项,下面一一说明。打开php.ini配置文件找到File Upl...2015-10-21
  • ant design中upload组件上传大文件,显示进度条进度的实例

    这篇文章主要介绍了ant design中upload组件上传大文件,显示进度条进度的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-29
  • C#使用StreamWriter写入文件的方法

    这篇文章主要介绍了C#使用StreamWriter写入文件的方法,涉及C#中StreamWriter类操作文件的相关技巧,需要的朋友可以参考下...2020-06-25
  • php实现文件下载实例分享

    举一个案例:复制代码 代码如下:<?phpclass Downfile { function downserver($file_name){$file_path = "./img/".$file_name;//转码,文件名转为gb2312解决中文乱码$file_name = iconv("utf-8","gb2312",$file_name...2014-06-07