【问题标题】:PHP - Can't check session while script is executingPHP - 脚本执行时无法检查会话
【发布时间】:2014-12-11 12:21:51
【问题描述】:

我正在编写一个执行时间很长的 php 脚本,我希望能够告诉客户端脚本的进度。

我不能通过输出缓冲来做到这一点,因为脚本是通过 AJAX 调用的(我想保持这种方式)。

我偶然发现了一个解决方案,您可以将进度保存到 $_SESSION 变量并连续调用另一个 PHP 脚本以从 $_SESSION 获取进度。

但是,在我的实现中,这些调用在主(长)进程完成之前不会执行。在 Chrome 开发工具窗口中,调用与主 AJAX 调用一起显示为“待处理”,并且它们都在主调用完成后立即返回进度。

这是主要的长脚本(测试代码):

<?php
@session_start();
for($i=0; $i<10; $i++)
{
    $_SESSION["progress"] = $i;
    sleep(2);
}

这是更新脚本

<?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 客户端检索进度?

【问题讨论】:

  • 如何将进度写入数据库而不是通过javascript检索结果?
  • 会有什么不同?
  • 与php分离。可能符合 if(progress
  • 我认为问题可能是您的onprogress 仅在第一个 ajax 完成时才被调用,因为它不是可以返回进度的 ajax 调用。尝试同时启动你的第一个 ajax 和第二个 ajax,一个接一个。
  • onprogress 与 AJAX 无关。那只是显示上传进度,不是php执行进度。

标签: javascript php jquery ajax session


【解决方案1】:

根据这篇文章 (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);
}

新的检查进度

@session_start();
if(isset($_SESSION["pages-processed"]))
    echo $_SESSION["pages-processed"];
else
    echo 0;

现在它就像一个魅力:)

【讨论】:

    【解决方案2】:

    使用

    async=false;
    

    在你的 ajax 请求中

    在你的代码中你已经循环了很长时间的php,页面只会在执行后加载,所以你只会得到最后一个进度值

    【讨论】:

    • 我一点击提交,整个页面就挂了
    猜你喜欢
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多