title: How to show PHP curl progress with AJAX
body: <p>I'm writing a PHP web app using the <a href="http://cakephp.org/" rel="nofollow">CakePHP</a> framework (v2.x). On one of my views there is a form which uploads a big video file to a 3rd party API. The files are big, so the upload can easily take a minute or two. So I'm submitting the form with AJAX and showing the user a dancing hippo (or whatever) so they know the wheels are still turning. Here's that script, which uses the <a href="http://malsup.com/jquery/form/" rel="nofollow">jquery form plugin</a>:</p>
  
  <pre><code>&lt;script&gt;
  var options = {
      //complete : callback_function...,
      //error : callback_function...,
      beforeSend : function() {
          $("#MediaSubmitForm").hide();
          $("#MediaSubmitForm").after('&lt;img class="hula-hippo" src="/img/hippo-hula.gif" /&gt;');
  
      },
      success : function(data){
          $(".hula-hippo").hide();
          $("#MediaSubmitForm").after("&lt;h3&gt;Upload complete!&lt;/h3&gt;");
          console.log(data);
      },
      uploadProgress: function(event, position, total, percentComplete){
          console.log(percentComplete);
      }
  
  };
  $("#MediaSubmitForm").ajaxForm(options);
  &lt;/script&gt;
  </code></pre>
  
  <p>In order to not expose our API key to the client, I submit the form to a controller action, which makes the actual POST request from the server to the API using curl. Here is that method (and one callback).</p>
  
  <pre><code>//uploads a video to a project through the API
  public function apiUpload( $tmp_filename, $project_hashed_id ) {
      $api_password = 'xxxxxxxxxx';
      $username = 'api';
      $data = array(
          'api_password'  =&gt; $api_password,
          'file'          =&gt; '@'.$tmp_filename,
          'project_id'    =&gt; $project_hashed_id
          );
  
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_URL, "https://upload.wistia.com" );
      curl_setopt($ch, CURLOPT_POSTFIELDS, $data);    
      curl_setopt($ch, CURLOPT_NOPROGRESS, FALSE);    
      curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, array($this, 'apiUploadCallback'));  
      $result = curl_exec($ch); //***Note A***
      curl_close($ch);
      return( json_decode($result) );
  
  }
  
  //BE CAREFUL... PHP 5.5 Added the cURL resource as the first argument to the CURLOPT_PROGRESSFUNCTION callback 
  protected function apiUploadCallback( $total_bytes_down_expected, $bytes_down_so_far, $total_bytes_up_expected, $total_bytes_up_so_far ) {
      if ($total_bytes_up_expected &gt; 0)
          //error_log( round( ($total_bytes_up_so_far / $total_bytes_up_expected)*100) );
          echo ( round( ($total_bytes_up_so_far / $total_bytes_up_expected)*100) ); //***Note B***
  }
  </code></pre>
  
  <p>This works, but it would be <strong>much</strong> better if I could show the user the actual progress of the upload. I've figured out how to calculate this with the callback function (see <code>***Note B***</code>), but I'm not sure how to pass it back to the page (where the user is waiting). I tried using jQuery's <code>uploadProgress</code> but it shows the progress of the file uploading to our server... <em>NOT</em> the progress of the upload to the API. I tried echoing the progress from the curl callback (<code>***Note B***</code>) but it spits out a series of numbers which tangle with the json object returned by the api (<code>***Note A***</code>), which I also need. Something like this:</p>
  
  <pre><code>11112222233344444...9898989899999999999999{api:"response mixed in here"}100100100100
  </code></pre>
  
  <p>How can I capture the curl progress AND the subsequent API response?</p>