【问题标题】:Save image from url with curl PHP使用 curl PHP 从 url 保存图像
【发布时间】:2011-09-22 12:04:49
【问题描述】:

我需要使用 CURL 从 url 保存图像并将其保存到我服务器上的文件夹中。我一直在与此代码作斗争,但无济于事。理想情况下,我想抓取图像并将其保存为“photo1”或其他内容。帮助!

    function GetImageFromUrl($link)

    {

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_POST, 0);

    curl_setopt($ch,CURLOPT_URL,$link);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    $result=curl_exec($ch);

    curl_close($ch);

    return $result;

    }

    $sourcecode = GetImageFromUrl($iticon);

    $savefile = fopen(' /img/uploads/' . $iconfilename, 'w');
    fwrite($savefile, $sourcecode);
    fclose($savefile);

【问题讨论】:

    标签: php image curl


    【解决方案1】:

    如果您想从 https 下载图像:

    $output_filename = 'output.png';
    $host = "https://.../source.png"; // <-- Source image url (FIX THIS)
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $host);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_AUTOREFERER, false);
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // <-- don't forget this
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // <-- and this
    $result = curl_exec($ch);
    curl_close($ch);
    $fp = fopen($output_filename, 'wb');
    fwrite($fp, $result);
    fclose($fp);
    

    【讨论】:

    • 您的代码解决了我的 The requested URL returned error: 503 Service Unavailable 问题。谢谢您,先生,祝您有愉快的一天。
    【解决方案2】:

    这是最简单的实现。

    function downloadFile($url, $path)
    {
        $newfname = $path;
        $file = fopen($url, 'rb');
        if ($file) {
            $newf = fopen($newfname, 'wb');
            if ($newf) {
                while (!feof($file)) {
                    fwrite($newf, fread($file, 1024 * 8), 1024 * 8);
                }
            }
        }
        if ($file) {
            fclose($file);
        }
        if ($newf) {
            fclose($newf);
        }
    }
    

    【讨论】:

      【解决方案3】:

      Komang答案的改进版(添加referer和用户代理,检查是否可以写入文件),如果可以则返回true,如果有错误则返回false:

      public function downloadImage($url,$filename){
          if(file_exists($filename)){
              @unlink($filename);
          }
          $fp = fopen($filename,'w');
          if($fp){
              $ch = curl_init ($url);
              curl_setopt($ch, CURLOPT_HEADER, 0);
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
              curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
              $result = parse_url($url);
              curl_setopt($ch, CURLOPT_REFERER, $result['scheme'].'://'.$result['host']);
              curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0');
              $raw=curl_exec($ch);
              curl_close ($ch);
              if($raw){
                  fwrite($fp, $raw);
              }
              fclose($fp);
              if(!$raw){
                  @unlink($filename);
                  return false;
              }
              return true;
          }
          return false;
      }
      

      【讨论】:

      • CURLOPT_RETURNTRANSFER 首先将整个文件读取到 php 变量中。它速度较慢,并且可能会破坏大文件。改为使用CURLOPT_FILE 传递文件指针。
      【解决方案4】:

      选项#1

      您可以使用CURLOPT_FILE 选项直接将文件显示到 curl 以供下载,而不是将二进制/原始数据放入变量中然后写入。

      函数如下:

      // takes URL of image and Path for the image as parameter
      function download_image1($image_url, $image_file){
          $fp = fopen ($image_file, 'w+');              // open file handle
      
          $ch = curl_init($image_url);
          // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // enable if you want
          curl_setopt($ch, CURLOPT_FILE, $fp);          // output to file
          curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
          curl_setopt($ch, CURLOPT_TIMEOUT, 1000);      // some large value to allow curl to run for a long time
          curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
          // curl_setopt($ch, CURLOPT_VERBOSE, true);   // Enable this line to see debug prints
          curl_exec($ch);
      
          curl_close($ch);                              // closing curl handle
          fclose($fp);                                  // closing file handle
      }
      

      你应该这样称呼它:

      // test the download function
      download_image1("http://www.gravatar.com/avatar/10773ae6687b55736e171c038b4228d2", "local_image1.jpg");
      

      选项 #2

      现在,如果你想下载一个非常大的文件,上面那个例子的功能可能不太好用。这次你可以使用下面的函数来处理一个大文件。此外,您可以根据需要打印进度(% 或任何其他格式)。下面的函数是使用callback函数实现的,该函数在下载过程中将数据块写入文件中。

      // takes URL of image and Path for the image as parameter
      function download_image2($image_url){
          $ch = curl_init($image_url);
          // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // enable if you want
          curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
          curl_setopt($ch, CURLOPT_TIMEOUT, 1000);      // some large value to allow curl to run for a long time
          curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
          curl_setopt($ch, CURLOPT_WRITEFUNCTION, "curl_callback");
          // curl_setopt($ch, CURLOPT_VERBOSE, true);   // Enable this line to see debug prints
          curl_exec($ch);
      
          curl_close($ch);                              // closing curl handle
      }
      
      /** callback function for curl */
      function curl_callback($ch, $bytes){
          global $fp;
          $len = fwrite($fp, $bytes);
          // if you want, you can use any progress printing here
          return $len;
      }
      

      这里是如何调用这个函数:

      // test the download function
      $image_file = "local_image2.jpg";
      $fp = fopen ($image_file, 'w+');              // open file handle
      download_image2("http://www.gravatar.com/avatar/10773ae6687b55736e171c038b4228d2");
      fclose($fp);                                  // closing file handle
      

      【讨论】:

        【解决方案5】:

        试试这个:

        function grab_image($url,$saveto){
            $ch = curl_init ($url);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
            $raw=curl_exec($ch);
            curl_close ($ch);
            if(file_exists($saveto)){
                unlink($saveto);
            }
            $fp = fopen($saveto,'x');
            fwrite($fp, $raw);
            fclose($fp);
        }
        

        并确保在 php.ini 中启用 allow_url_fopen

        【讨论】:

        • 谢谢!我会继续尝试这件事,看看是否有效。
        • 请记住,编码良好的网站会寻找用户代理。每个浏览器、平板电脑或手机都会有一个用户代理!如果您仍然无法获取图像,很可能是因为用户代理检测,请添加此...curl_setopt($ch,CURLOPT_USERAGENT,'MyImage Collector +http://www.yourdomainname/mybot.html'); 或欺骗真实的curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
        • 这样保存图像时是否有文件大小限制? PHP配置中的文件上传限制会影响这个吗?
        • "确保在 php.ini 中启用了 allow_url_fopen" 我们需要这个设置吗?
        • 你真的应该为那个'unlink'函数添加一个警告——如果你不小心它是非常危险的。菜鸟当心!
        猜你喜欢
        • 1970-01-01
        • 2010-10-17
        • 1970-01-01
        • 1970-01-01
        • 2020-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多