zoukankan      html  css  js  c++  java
  • 分享一个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;
        }

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

  • 相关阅读:
    [易语言] 六边形扫雷游戏实战开发
    [web开发] 利用微信小程序开发上海大学失物招领平台
    [web开发] Vue + spring boot + echart 微博爬虫展示平台
    [web开发] Vue+Spring Boot 上海大学预约系统开发记录
    [神经网络]一步一步使用Mobile-Net完成视觉识别(一)
    Python中操作ini配置文件
    python操作mySQL数据库
    使用python和selenium写一个百度搜索的case
    功能测试的过程中有关数据安全性的检查点
    python主流测试框架的简介
  • 原文地址:https://www.cnblogs.com/helloprogram/p/2416492.html
Copyright © 2011-2022 走看看