title: Why does multi cURL download files with 0 bits as size?
body: <p>I use this class for multi thread cUrl file download;</p>
  
  <p>On a local machine it downloads the files content, live the files are empty;</p>
  
  <p>What am i missing ?</p>
  
  <pre><code>&lt;?php
  
  /**
   * Crawler class file.
   *
   * CRAWLER
   *
   */
  class CrawlerCommand extends CConsoleCommand {
  
      private $instance_crawler_id;
      private $instance_crawler_url_limit = 10;
      public $multi_exec_curl_files = array();
      public $collection = array();
      public static $userAgents = array(
          'FireFox3' =&gt; 'Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9) Gecko/2008052906 Firefox/3.0',
          'GoogleBot' =&gt; 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
          'IE7' =&gt; 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
          'Netscape' =&gt; 'Mozilla/4.8 [en] (Windows NT 6.0; U)',
          'Opera' =&gt; 'Opera/9.25 (Windows NT 6.0; U; en)'
      );
      public static $options = array(
          CURLOPT_USERAGENT =&gt; 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
          CURLOPT_AUTOREFERER =&gt; true,
          CURLOPT_FOLLOWLOCATION =&gt; true,
          CURLOPT_RETURNTRANSFER =&gt; true,
          CURLOPT_FRESH_CONNECT =&gt; true,
          CURLOPT_COOKIEJAR =&gt; "cookies.txt",
          CURLOPT_COOKIEFILE =&gt; "cookies.txt",
          CURLOPT_SSL_VERIFYPEER =&gt; false,
          CURLOPT_CONNECTTIMEOUT =&gt; 5,
          CURLOPT_TIMEOUT =&gt; 10,
              //CURLOPT_COOKIESESSION =&gt; false,
      );
  
      /**
       * Executes the command.
       * @param array command line parameters for this command.
       */
      public function run($args) {
          // $args gives an array of the command-line arguments for this command
  
          for ($i = 0; $i &lt; 50; $i++) {
              echo PHP_EOL;
          }
  
          //check if we need to create a new crawler instance; if all html sources from the active url's have been downloaded, there is no point to recrawl
          $day = date('d', time());
          $sql = "select * from `url` where `instance_crawler_day`!='$day' and `status`='1' order by `id` asc limit $this-&gt;instance_crawler_url_limit;";
          $cmd = Yii::app()-&gt;db-&gt;createCommand($sql);
          $rows = $cmd-&gt;queryAll();
  
          $actual_files = count($rows);
          //are there any files left to download for today ?
          if ($actual_files &gt; 0) {
  
              //creating a new unique crawler instance
              $model_instance_crawler = new InstanceCrawler();
              $model_instance_crawler-&gt;day = $day;
              $model_instance_crawler-&gt;month = date('m', time());
              $model_instance_crawler-&gt;year = date('Y', time());
              if ($model_instance_crawler-&gt;save()) {
  
                  //locking x url's for the crawler to download time at a time
                  $sql = "update `url` set `instance_crawler_id`='$model_instance_crawler-&gt;id', `instance_crawler_day`='$model_instance_crawler-&gt;day' where `instance_crawler_day`!='$model_instance_crawler-&gt;day' and `status`='1' limit $this-&gt;instance_crawler_url_limit;";
                  $cmd = Yii::app()-&gt;db-&gt;createCommand($sql);
                  $cmd-&gt;query();
  
                  $robots_txt = new RobotsTXT();
  
                  $robots_txt-&gt;load_robots_from_db();
  
                  $time = strtotime('-60 days');
  
                  $sql = "SELECT u.*
  FROM url AS u
  JOIN product p ON p.`url_id` = u.id
  JOIN product_follower pf ON pf.`product_id` = p.`id` AND pf.`created`&gt;:time
  JOIN `user` us ON us.id = pf.`user_id`
  WHERE us.`status` = 1
  GROUP BY u.id
  order by `u`.`website_id` asc";
  
                  //selecting x rows that belong to the new crawler instance
                  $sql = "select * from `url` where `instance_crawler_id`='$model_instance_crawler-&gt;id' and `instance_crawler_day`='$day' and `status`='1' order by `id` asc;";
                  $cmd = Yii::app()-&gt;db-&gt;createCommand($sql);
                  $rows = $cmd-&gt;queryAll();
  
                  if (count($rows) &gt; 0) {
  
                      foreach ($rows as $row) {
                          $this-&gt;collection[$row['website_id']]['items'][] = $row;
                      }
  
                      foreach (array_keys($this-&gt;collection) as $key) {
  
                          $this-&gt;collection[$key]['urls'] = 0;
  
                          $collection2[] = $this-&gt;collection[$key];
                      }
  
                      $this-&gt;collection = $collection2;
  
                      $collection2 = null;
  
                      $this-&gt;processCollection();
  
                      //on dew, comment
                      $this-&gt;multiCurl($this-&gt;multi_exec_curl_files);
                      //CurlTool::downloadFile($url, $fileName, $fields = null, $verbose = false);
                  }
              }
          } else {
              echo 'There are no files left to download today. Come back tomorow.' . PHP_EOL;
          }
  
          echo PHP_EOL . 'DONE' . PHP_EOL;
      }
  
      /**
       * Provides the command description.
       * This method may be overridden to return the actual command description.
       * @return string the command description. Defaults to 'Usage: php entry-script.php command-name'.
       */
      public function getHelp() {
          return 'Usage: how to use this command';
      }
  
      private function checkCounters() {
          $status = false;
          foreach ($this-&gt;collection as $key =&gt; $value) {
              if ($value['urls'] &lt; count($value['items']))
                  $status = true;
          }
          return $status;
      }
  
      public function processCollection() {
          //print'&lt;pre&gt;';
          //print_r($this-&gt;collection);
          $w = 0;
          while ($this-&gt;checkCounters()) {
              foreach ($this-&gt;collection as $key =&gt; $value)
                  if ($value['urls'] &lt; count($value['items'])) {
                      echo 'downloading file: ' . ($value['items'][$value['urls']]['id']) . '.html' . PHP_EOL;
                      //prepare the array for the multi thread cURL downloading process
                      $this-&gt;multi_exec_curl_files[$value['items'][$value['urls']]['id']] = array('link' =&gt; $value['items'][$value['urls']]['link']);
                      //$this-&gt;downloadFile($value['items'][$value['urls']]['url'], CRAWLER_FILES . ($value['items'][$value['urls']]['id']) . '.html');
                      //echo $value['items'][$value['urls']]['link'].'&lt;br&gt;';
                      //CurlTool::downloadFile($value['items'][$value['urls']]['link'], ($value['items'][$value['urls']]['id']) . '.html');
                      $this-&gt;collection[$key]['urls']++;
                  }
              $w++;
              if ($w &gt; count($this-&gt;collection))
                  $w = 0;
          }
      }
  
      public function multiCurl($res, $options = "") {
  
          if (count($res) &lt;= 0)
              return False;
  
          $handles = array();
  
          if (!$options) // add default options
              $options = self::$options;
  
          // add curl options to each handle
          foreach ($res as $k =&gt; $row) {
              $ch{$k} = curl_init();
              $options[CURLOPT_URL] = $row['link'];
              curl_setopt_array($ch{$k}, $options);
              $handles[$k] = $ch{$k};
          }
  
          $mh = curl_multi_init();
  
          foreach ($handles as $k =&gt; $handle) {
              curl_multi_add_handle($mh, $handle);
          }
  
          $running_handles = null;
          //execute the handles
          do {
              $status_cme = curl_multi_exec($mh, $running_handles);
          } while ($cme == CURLM_CALL_MULTI_PERFORM);
  
          while ($running_handles &amp;&amp; $status_cme == CURLM_OK) {
              if (curl_multi_select($mh) != -1) {
                  do {
                      $status_cme = curl_multi_exec($mh, $running_handles);
                  } while ($status == CURLM_CALL_MULTI_PERFORM);
              }
          }
  
          foreach ($res as $k =&gt; $row) {
              $res[$k]['error'] = curl_error($handles[$k]);
              print_r($res[$k]['error']);
              if (!empty($res[$k]['error'])) {
                  $res[$k]['data'] = '';
              } else {
                  //$res[$k]['data'] = curl_multi_getcontent($handles[$k]);  // get results
                  file_put_contents(CRAWLER_FILES . $k . '.html', curl_multi_getcontent($handles[$k]));
              }
  
              // close current handler
              curl_multi_remove_handle($mh, $handles[$k]);
          }
          curl_multi_close($mh);
          return $res; // return response
      }
  
  }
  </code></pre>