首页 > 编程技术 > php

php中file_get_contents函数高级用法

发布时间:2016-11-25 16:45

file_get_contents函数我们通常是拿来对文件操作了,下面一起来看看file_get_contents函数的高级使用方法吧.


首先解决file_get_contents的超时问题,在超时返回错误后就象js中的settimeout那样进行一次尝试,错误超过3次或者5次后就确认为无法连线伺服器而彻底放弃。
这?就简单介绍两种解决方法:

一、增加超时的时间限制

注意:set_time_limit只是设定你的PHP程式的超时时间,而不是file_get_contents函数读取URL的超时时间。
我一开始以为set_time_limit也能影响到file_get_contents,后来经测试是无效的。真正的修改file_get_contents延时可以用resource $context的timeout参数:
PHP程式码

    $opts = array(
        'http'=>array(
            'method'=>"GET",
            'timeout'=>60,
        )
    );

    $context = stream_context_create($opts);

    $html =file_get_contents('http://www.111cn.net', false, $context);
    fpassthru($fp);

二、多次尝试

PHP程式码
    $cnt=0;
    while($cnt < 3 && ($str=@file_get_contents('http...'))===FALSE){
      $cnt++;
    }

以上方法对付超时已经OK了。接下来演示一下用file_get_contents实现Post,如下:
PHP程式码

    function Post($url, $post = null){
        $context = array();
        if (is_array($post)) {
            ksort($post);

            $context['http'] = array (
                'timeout'=>60,
                'method' => 'POST',
                'content' => http_build_query($post, '', '&'),
             );
        }

        return file_get_contents($url, false, stream_context_create($context));
    }

    $data = array (
        'name' => 'test',
        'email' => 'test@gmail.com',
        'submit' => 'submit',
     );

     echo Post('http://www.111cn.net', $data);

注意档案头的Set_time_out否则整个档案都得超时了

magic_quotes_gpc是用来判断我们apache是不是开启了自动转译功能了,为了让各位更好的理解魔法引用magic_quotes_gpc()函数用法下面来给各位总结与举一些例子。

magic_quotes_gpc的设定值将会影响通过Get/Post/Cookies获得的数据


这两天接入百度SDK处理支付回调时碰到了签名通不过的情况,签名规则很简单,md5(transdata + appkey) 和 接受到的sign比较,请求方式为POST。

于是乎通过php://input记录下了原始数据和记录下了POST数据,通过日志查看到结果类似如下:

//原始数据
transdata={"exorderno":"2014031223","transid":"05514312314566",
"waresid":1,"appid":"1","feetype":0,"money":1,"count":1,"result":0,
"transtype":0,"transtime":"2014-03-12 15:33:19","paytype":401}&sign=xxxx
 
//post数据
[transdata] => {\"exorderno\":\"2014031223452345234\",\"transid\":
\"05514031215312314566\",\"waresid\":1,\"appid\":\"1\",\"feetype\":0,
\"money\":1,\"count\":1,\"result\":0,\"transtype\":0,
\"transtime\":\"2014-03-12 15:33:19\",\"paytype\":401}
[sign] => xxxx

可见接收到post数据时引号自动转义了,而程序上未做到该操作,很容易就联想到服务器的魔法引用打开了,查看
php版本

PHP 5.2.14 (cli) (built: Jun 7 2012 20:39:40)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies

例子说明:

$data1 = $_POST['aaa']; 

 $data2 = implode(file('1.txt')); 

 if(get_magic_quotes_gpc()){ 

    //把数据$data1直接写入数据库 (自动转译) 

 }else{ 

    $data1 = addslashes($data1); 

    //把数据$data1写入数据库,用函数(addslashes()转译) 

 } 

 if(get_magic_quotes_runtime()){ 

    //把数据$data2直接写入数据库(自动转译) 

 //从数据库读出的数据要经过一次stripslashes()之后输出,stripslashes()的作用是去掉:\ ,和addslashes()作用相反 

 }else{ 

    $data2 = addslashes($data2); 

     //把数据$data2写入数据库 

   

 //从数据库读出的数据直接输出 

}

最关键的区别是就是上面提到的2点:他们针对的处理对象不同

magic_quotes_gpc的设定值将会影响通过Get/Post/Cookies获得的数据

注意的是没有 set_magic_quotes_gpc()这个函数,就是不能在程序里面设置magic_quotes_gpc的值。

魔法引用5.4才删掉的,那极有可能这里打开在,查看配置文件确实如此,根据条件开关strip一下即可。

问题很快就解决了,但如果不熟悉这块可能还需要点时间,之前在CI的全局参数xss设置中有类似的地方,当进行全局处理之后对于这种接口、密钥可能会带来一些影响,所以全局参数过滤需要注意点。

矛盾可分为主要矛盾和次要矛盾,我们在程序设计中也常有这种思想,改最少的地方,过滤大部分参数,少数特殊处理。php中把它去掉了并不说明它没有存在的价值,有了魔法引用少了很多注入,但同时也让一些东西变得混乱,哪里需要转义,要怎么转义,通过什么方式来转义等等。客观看待,汲取中间有用的部分

提取链接是一个很简单的做法了,下面这个例子相对来讲是比较全面了,下面我们一起来看看这个php curl采集页面内容并提取所有的链接例子.

本文承接上面两篇,本篇中的示例要调用到前两篇中的函数,做一个简单的URL采集。一般php采集网络数据会用file_get_contents、file和cURL。不过据说cURL会比file_get_contents、file更快更专业,更适合采集。今天就试试用cURL来获取网页上的所有链接。示例如下:


<?php
/*
 * 使用curl 采集111cn.net下的所有链接。
 */
include_once('function.php');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.111cn.net/');
// 只需返回HTTP header
curl_setopt($ch, CURLOPT_HEADER, 1);
// 页面内容我们并不需要
// curl_setopt($ch, CURLOPT_NOBODY, 1);
// 返回结果,而不是输出它
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$html = curl_exec($ch);
$info = curl_getinfo($ch);
if ($html === false) {
 echo "cURL Error: " . curl_error($ch);
}
curl_close($ch);
$linkarr = _striplinks($html);
// 主机部分,补全用
$host = 'http://www.111cn.net/';
if (is_array($linkarr)) {
 foreach ($linkarr as $k => $v) {
  $linkresult[$k] = _expandlinks($v, $host);
 }
}
printf("<p>此页面的所有链接为:</p><pre>%s</pre>n", var_export($linkresult , true));
?>


function.php内容如下(即为上两篇中两个函数的合集):

<?php
function _striplinks($document) {
 preg_match_all("'<s*as.*?hrefs*=s*(["'])?(?(1) (.*?)\1 | ([^s>]+))'isx", $document, $links);
 // catenate the non-empty matches from the conditional subpattern
 while (list($key, $val) = each($links[2])) {
  if (!empty($val))
   $match[] = $val;
 } while (list($key, $val) = each($links[3])) {
  if (!empty($val))
   $match[] = $val;
 }
 // return the links
 return $match;
}
/*===================================================================*
 Function: _expandlinks
 Purpose: expand each link into a fully qualified URL
 Input:  $links   the links to qualify
    $URI   the full URI to get the base from
 Output:  $expandedLinks the expanded links
*===================================================================*/
function _expandlinks($links,$URI)
{
 $URI_PARTS = parse_url($URI);
 $host = $URI_PARTS["host"];
 preg_match("/^[^?]+/",$URI,$match);
 $match = preg_replace("|/[^/.]+.[^/.]+$|","",$match[0]);
 $match = preg_replace("|/$|","",$match);
 $match_part = parse_url($match);
 $match_root =
 $match_part["scheme"]."://".$match_part["host"];
 $search = array(  "|^http://".preg_quote($host)."|i",
      "|^(/)|i",
      "|^(?!http://)(?!mailto:)|i",
      "|/./|",
      "|/[^/]+/../|"
     );
 $replace = array( "",
      $match_root."/",
      $match."/",
      "/",
      "/"
     );
 $expandedLinks = preg_replace($search,$replace,$links);
 return $expandedLinks;
}
?>


具体想要和file_get_contents做一个比较的话,可以利用linux下的time命令查看两者执行各需多长时间。据目前测试看是CURL更快一些。最后链接下上面两个函数相关介绍。

匹配链接函数: function _striplinks()

相对路径转绝对:function _expandlinks()

在做文件上传时有一个非常必须要做的功能就是上传文件会按日期生成目录并把文件保存在目录下了,下面我来为各位介绍一段php自动创建目录并保存文件函数

php保存文件,还可以根据文件路径自动连续创建目录,代码如下(注:PHP要版本5以上):

<?php
 /**
  * 保存文件
  *
  * @param string $fileName 文件名(含相对路径)
  * @param string $text 文件内容
  * @return boolean
  */
 function saveFile($fileName, $text) {
  if (!$fileName || !$text)
   return false;
  if (makeDir(dirname($fileName))) {
   if ($fp = fopen($fileName, "w")) {
    if (@fwrite($fp, $text)) {
     fclose($fp);
     return true;
    } else {
     fclose($fp);
     return false;
    }
   }
  }
  return false;
 }
 /**
  * 连续创建目录
  *
  * @param string $dir 目录字符串
  * @param int $mode 权限数字
  * @return boolean
  */
 function makeDir($dir, $mode=0755) {
   /*function makeDir($dir, $mode="0777") { 此外0777不能加单引号和双引号,
  加了以后,"0400" = 600权限,处以为会这样,我也想不通*/
  if (!dir) return false;
  if(!file_exists($dir)) {
   return mkdir($dir,$mode,true);
  } else {
   return true;
  }
 }
?>
//以下是测试内容,并调用上面的函数
<?php
 $content = '这里是测试内容';
 if(saveFile('dir/test.txt',$content)){
  echo '写入成功';
 }else{
  echo '写入失败';
 }
?>

注意:makeDir就是一个目录创建函数,我们使用的是递归创建了.

下文给各位介绍一个PHP中number_format函数输出数字格式化,增加千分位符号,如果有需要的朋友可一起来看看.

在输出数据到屏幕上显示的时候,如果数据较大,位数较多,看上去会比较费劲,有一种比较直观的方法是使用千分位,也就是每三位数字显示一个逗号,这样可以快速的知道数的大小,不用一位位的去慢慢数了。

令人高兴的是,php中有专门的函数可以完成这个任务,可以在输出数据的时候自动加上千分位。

string number_format ( float number [, int decimals [, string dec_point, string thousands_sep]] )

number_format有四个参数,第一个参数是要输出的数字(浮点类型),这个参数是必需的,后面三个参数为可选的,其中后面两个参数要么全没有,要么全提供

number      必需。要格式化的数字。如果未设置其他参数,则数字会被格式化为不带小数点且以逗号 (,) 作为分隔符。

decimals    可选。规定多少个小数。如果设置了该参数,则使用点号 (.) 作为小数点来格式化数字。

decimalpoint    可选。规定用作小数点的字符串。

separator    可选。规定用作千位分隔符的字符串。仅使用该参数的第一个字符。比如 “xyz” 仅输出 “x”。

string number_format(
  float number,  //要输出的数字
  int decimals,  //小数位的位数,默认为0
  string dec_point, //小数点的表示,默认为.
  string thousands_sep //千分位的表示,默认为,
)

下面搞个例子试试

echo number_format('1234.56');
echo number_format('1234.56',1);
echo number_format('1234.56',2);
echo number_format('1234.56',3);
echo number_format('1234.56',2,'-','/');

结果如下

1,235   // 四舍五入
1,234.6   //
1,234.56  //
1,234.560  // 小数位不足,补充0
1/234-56  // 千分位符号变成/,小数点符号变为-

例子

number_format

<?php

$number = 1234.56;

// english notation (default)
$english_format_number = number_format($number);
// 1,235

// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
// 1 234,56

$number = 1234.5678;

// english notation without thousands seperator
$english_format_number = number_format($number, 2, '.', '');
// 1234.57

?>

标签:[!--infotagslink--]

您可能感兴趣的文章: