分享一个PHP下载远程图片的函数

/**
  * 抓取远程图片
  *
  * @param string $url 远程图片路径
  * @param string $filename 本地存储文件名
  */
function  grabImage( $url , $filename  = '' ) {
     if ( $url  == '' ) {
         return  false; //如果 $url 为空则返回 false;
     }
     $ext_name  = strrchr ( $url , '.' ); //获取图片的扩展名
     if ( $ext_name  != '.gif'  && $ext_name  != '.jpg'  && $ext_name  != '.bmp'  && $ext_name  != '.png' ) {
         return  false; //格式不在允许的范围
     }
     if ( $filename  == '' ) {
         $filename  = time(). $ext_name ; //以时间戳另起名
     }
     //开始捕获
     ob_start();
     readfile( $url );
     $img_data  = ob_get_contents();
     ob_end_clean();
     $size  = strlen ( $img_data );
     $local_file  = fopen ( $filename  , 'a' );
     fwrite( $local_file , $img_data );
     fclose( $local_file );
     return  $filename ;
}

 

上面的函数有几个缺点:

1.不能自动识别图片后缀名(很多图片的url并不指向一个静态图片地址,而是直接将图片流输出到客户端)

2.不支持图片url的302跳转 

这个函数并不符合本人项目的需求,于是花了点时间自己写了一个下载函数,此函数支持:

1.静态图片下载

2.服务端直接输出图片流下载

3.服务端使用302跳转到真实图片地址的下载(可限定跳转次数)

函数代码如下:

?
/**
      * 下载远程图片
      * @param string $url 图片的绝对url
      * @param string $filepath 文件的完整路径(包括目录,不包括后缀名,例如/www/images/test) ,此函数会自动根据图片url和http头信息确定图片的后缀名
      * @return mixed 下载成功返回一个描述图片信息的数组,下载失败则返回false
      */
     function  downloadImage( $url , $filepath ) {
         //服务器返回的头信息
         $responseHeaders  = array ();
         //原始图片名
         $originalfilename  = '' ;
         //图片的后缀名
         $ext  = '' ;
         $ch  = curl_init( $url );
         //设置curl_exec返回的值包含Http头
         curl_setopt( $ch , CURLOPT_HEADER, 1);
         //设置curl_exec返回的值包含Http内容
         curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1);       
         //设置抓取跳转(http 301,302)后的页面
         curl_setopt( $ch , CURLOPT_FOLLOWLOCATION, 1);
         //设置最多的HTTP重定向的数量
         curl_setopt( $ch , CURLOPT_MAXREDIRS, 2);
 
         //服务器返回的数据(包括http头信息和内容)
         $html  = curl_exec( $ch );
         //获取此次抓取的相关信息
         $httpinfo  = curl_getinfo( $ch );
         curl_close( $ch );
         if  ( $html  !== false) {
             //分离response的header和body,由于服务器可能使用了302跳转,所以此处需要将字符串分离为 2+跳转次数 个子串
             $httpArr  = explode ( "\r\n\r\n" , $html , 2 + $httpinfo [ 'redirect_count' ]);
             //倒数第二段是服务器最后一次response的http头
             $header  = $httpArr [ count ( $httpArr ) - 2];
             //倒数第一段是服务器最后一次response的内容
             $body  = $httpArr [ count ( $httpArr ) - 1];
             $header .= "\r\n" ;
 
             //获取最后一次response的header信息
             preg_match_all( '/([a-z0-9-_]+):\s*([^\r\n]+)\r\n/i' , $header , $matches );
             if  (! empty ( $matches ) && count ( $matches ) == 3 && ! empty ( $matches [1]) && ! empty ( $matches [1])) {
                 for  ( $i  = 0; $i  < count ( $matches [1]); $i ++) {
                     if  ( array_key_exists ( $i , $matches [2])) {
                         $responseHeaders [ $matches [1][ $i ]] = $matches [2][ $i ];
                     }
                 }
             }
             //获取图片后缀名
             if  (0 < preg_match( '{(?:[^\/\\\\]+)\.(jpg|jpeg|gif|png|bmp)$}i' , $url , $matches )) {
                 $originalfilename  = $matches [0];
                 $ext  = $matches [1];
             } else  {
                 if  ( array_key_exists ( 'Content-Type' , $responseHeaders )) {
                     if  (0 < preg_match( '{image/(\w+)}i' , $responseHeaders [ 'Content-Type' ], $extmatches )) {
                         $ext  = $extmatches [1];
                     }
                 }
             }
             //保存文件
             if  (! empty ( $ext )) {
                 $filepath  .= ".$ext" ;
                 //如果目录不存在,则先要创建目录
                 CFiles::createDirectory(dirname( $filepath ));
                 $local_file  = fopen ( $filepath , 'w' );
                 if  (false !== $local_file ) {
                     if  (false !== fwrite( $local_file , $body )) {
                         fclose( $local_file );
                         $sizeinfo  = getimagesize ( $filepath );
                         return  array ( 'filepath'  => realpath ( $filepath ), 'width'  => $sizeinfo [0], 'height'  => $sizeinfo [1], 'orginalfilename'  => $originalfilename , 'filename'  => pathinfo ( $filepath , PATHINFO_BASENAME));
                     }
                 }
             }
         }
         return  false;
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值