如何用AJAX显示PHP curl的进度


How to show PHP curl progress with AJAX

我正在使用CakePHP框架(v2.x)编写一个PHP web应用程序。在我的一个视图中,有一个表单将一个大视频文件上传到第三方API。文件很大,所以上传很容易需要一两分钟。所以我用AJAX提交了表格,并向用户展示了一只跳舞的河马(或其他什么),这样他们就知道轮子还在转动。这是使用jquery表单插件的脚本:

<script>
var options = {
    //complete : callback_function...,
    //error : callback_function...,
    beforeSend : function() {
        $("#MediaSubmitForm").hide();
        $("#MediaSubmitForm").after('<img class="hula-hippo" src="/img/hippo-hula.gif" />');
    },
    success : function(data){
        $(".hula-hippo").hide();
        $("#MediaSubmitForm").after("<h3>Upload complete!</h3>");
        console.log(data);
    },
    uploadProgress: function(event, position, total, percentComplete){
        console.log(percentComplete);
    }
};
$("#MediaSubmitForm").ajaxForm(options);
</script>

为了不向客户端公开我们的API密钥,我将表单提交给一个控制器操作,该操作使用curl从服务器向API发出实际的POST请求。这是一个方法(和一个回调)。

//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'  => $api_password,
        'file'          => '@'.$tmp_filename,
        'project_id'    => $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 > 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***
}

这是可行的,但如果我能向用户显示上传的实际进度,效果会更好。我已经想好了如何使用回调函数来计算这个值(请参阅***Note B***),但我不知道如何将它传递回页面(用户正在等待)。我尝试使用jQuery的uploadProgress,但它显示了文件上传到我们服务器的进度上传到API的进度。我尝试从curl回调(***Note B***)中回显进度,但它抛出了一系列数字,这些数字与api返回的json对象(***Note A***)纠缠在一起,我也需要这些数字。类似这样的东西:

11112222233344444...9898989899999999999999{api:"response mixed in here"}100100100100

如何获取卷曲进度和随后的API响应?

您可以将进度状态存储在用户的会话中,然后使用ajax从会话中获取信息,然后将其显示在页面

您可以使用AJAX检查服务器上的状态,并让它每次调用一次。但这将垃圾邮件你的服务器没有必要,它需要每次一个新的HTTP请求。我建议你使用网络插座。然后直接在服务器和浏览器之间建立连接,这样服务器就可以在浏览器发生更新时直接发送进度更新。

是的,正如Moshen所说:

您可以将进度状态存储在用户的会话中,然后使用ajax从会话中获取信息,然后在页面上显示

但不要忘记调用"session_write_close()"

$nPourcent = round(($total_bytes_up_so_far / $total_bytes_up_expected)*100);
session_start();
$_SESSION['progress'] = $nPourcent;
session_write_close();