分享一个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;
    }

 经测试,此函数能应付绝大多数类型远程图片下载的处理。

 

转载于:https://www.cnblogs.com/helloprogram/archive/2012/03/25/2416492.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值