我正在编写一个执行时间很长的php脚本,我希望能够告诉客户端脚本的进度。
我无法通过输出缓冲执行此操作,因为脚本是通过AJAX调用的(并且我希望保持这种方式)。
我偶然发现了一个解决方案,您将进度保存到$ _SESSION变量,并连续调用另一个PHP脚本以从$ _SESSION获取进度。
但是,在我的实现中,这些调用在主(长)进程完成之前不会执行。在Chrome开发者工具窗口中,通话显示为"待定"以及主要的AJAX呼叫,它们都会在主呼叫结束后立即返回进度。
这是主要的长脚本(测试代码):
<?php
@session_start();
for($i=0; $i<10; $i++)
{
$_SESSION["progress"] = $i;
sleep(2);
}
这是更新脚本</ p>
<?php
if(isset($_SESSION["progress"]))
echo $_SESSION["progress"];
else
echo 0;
这是javascript
$("form#form-main").submit(function(e) {
e.preventDefault();
var $form = $(this);
var timeout_id;
$form.find("div#popup-overlay").show();
$.ajax(
{
url: $form.attr("action"),
type: $form.attr("method"),
data: new FormData($form[0]),
cache: false,
contentType: false,
processData: false,
xhr: function()
{
//get the native XmlHttpRequest object
var xhr = $.ajaxSettings.xhr();
//update progress
xhr.upload.onprogress = function(e)
{
if(e.lengthComputable)
{
var progress = Math.ceil(e.loaded / e.total * 100);
if(progress < 100)
$form.find("div#popup-content #status").text("UPLOADING " + progress + "%");
else
{
//start getting process progress from server
timeout_id = setInterval(
function()
{
$.post(
"CheckProgress.php",
function(data)
{
$form.find("div#popup-content #status").text("PROCESSED " + data + " pages");
}
);
},
300
);
}
}
};
//return the customized object
return xhr;
},
success: function(data)
{
$form.find("div#popup-content").html(data);
}
}
);
});
如何让javascript客户端检索进度?
答案 0 :(得分:2)
根据这篇文章(Using same session ID within two PHP scripts at same time),您无法使用相同的会话ID同时执行php脚本。这称为会话锁定。
解决方案是仅启动写入会话,并在之后立即关闭它,使会话ID不使用CheckProgress。
新长脚本
for($i=0; $i<10; $i++)
{
@session_start();
$_SESSION["pages-processed"] = $i;
session_write_close();
sleep(2);
}
新的CheckProgress
@session_start();
if(isset($_SESSION["pages-processed"]))
echo $_SESSION["pages-processed"];
else
echo 0;
现在它就像一个魅力:)
答案 1 :(得分:-1)
使用
async=false;
你的ajax请求中的
在你的代码中你已经长时间循环了php,页面只会在执行后加载,所以你只能得到进度的最后一个值