服务器发送了事件消息

时间:2016-05-18 19:34:28

标签: php server-sent-events

我一直在寻找一种方法来获取有关长时间运行脚本进度的反馈,并遇到了服务器发送的事件。我按照此处设置的指南http://www.htmlgoodies.com/beyond/reference/receive-updates-from-the-server-using-the-eventsource.html,复制了给出的示例,创建了几个php文件并将它们放在我的笔记本电脑上的本地主机服务器上(运行Apache Web服务器)。

他们工作得很好,服务器在浏览器中收到的消息循环的每一秒都返回一条消息。我在Firefox,Chrome和IE中进行了测试,当然IE只是报告了#34;不支持"消息如预期的那样。

在深入创建我的真实应用程序之前,我将这两个文件复制到我的制作公司服务器(运行IIS),然后从我的笔记本电脑上的同一浏览器中调用它们。

结果是我得到了所有的消息,但只是在循环完成之后,而不是在发送每个迭代消息时,这当然会使对象失败。

我错过了什么 - 可能在IIS服务器上有一些限制使用sse的设置吗?如果是这样的话?

任何帮助表示感谢。

以下是两个文件(除了名称更改之外,它们完全遵循关于该主题的多个介绍性网页上的示例):

第一个文件ssetest.php:

<?php

    echo "<!DOCTYPE html><html><head><meta charset=\"utf-8\" /></head><body>";

    echo "<script language='javascript' type='text/javascript'>

    var esSupport = false, es, result;

    function init() {
      noEsSupport = (window.EventSource === undefined);
      if(noEsSupport) addLog('This browser does not support server-sent events.<br>You will not get any progress messages.<br>Try Firefox or Chrome');
    }

    window.onload = init;

    function startTask() {
        es = new EventSource('ssetest_task.php');

        //a message is received
        es.addEventListener('message', function(e) {
            var result = JSON.parse( e.data );

            addLog(result.message);       

            if(e.lastEventId == 'CLOSE') {
                addLog('Received CLOSE closing');
                es.close();
                var pBar = document.getElementById('progressor');
                pBar.value = pBar.max; //max out the progress bar
            }
            else {
                var pBar = document.getElementById('progressor');
                pBar.value = result.progress;
                var perc = document.getElementById('percentage');
                perc.innerHTML   = result.progress  + \"%\";
                perc.style.width = (Math.floor(pBar.clientWidth * (result.progress/100)) + 15) + 'px';
            }
        });

        es.addEventListener('error', function(e){addLog('Error occurred'); es.close();});
    }

    function stopTask() {
        es.close();
        addLog('Interrupted');
    }

    function addLog(message) {
        var r = document.getElementById('results');
        r.innerHTML += message + '<br>';
        r.scrollTop = r.scrollHeight;
    }
    </script>";

    echo "<br />";
    echo "<input type=\"button\" onclick=\"startTask();\"  value=\"Start Long Task\" />";
    echo "<input type=\"button\" onclick=\"stopTask();\"  value=\"Stop Task\" />";
    echo "<br /><br />";
    echo "<p>Results</p>";
    echo "<br /><div id=\"results\" style=\"border:1px solid #000; padding:10px; width:300px; height:250px; overflow:auto; background:#eee;\"></div><br />";
    echo "<progress id='progressor' value='0' max='100'></progress> "; 
    echo "<span id=\"percentage\" style=\"text-align:right; display:block; margin-top:5px;\">0</span>";
    echo "</body></html>";

?>

和任务文件ssetest_task.php:

<?php

    header('Content-Type: text/event-stream');
    // recommended to prevent caching of event data.
    header('Cache-Control: no-cache'); 

    function send_message($id, $message, $progress) {
        $d = array('message' => $message , 'progress' => $progress);      
        echo "id: $id" . PHP_EOL;
        echo "data: " . json_encode($d) . PHP_EOL;
        echo PHP_EOL;      
        ob_flush();
        flush();
    }

    //LONG RUNNING TASK
    for($i = 1; $i <= 10; $i++) {
        send_message($i, 'on iteration ' . $i . ' of 10' , $i*10); 
        sleep(1);
    }

    send_message('CLOSE', 'Process complete');

?>

1 个答案:

答案 0 :(得分:0)

我已经使用随后的web.config设置在IIS上克服了这些问题。重要的是设置PHP的responseBufferLimit=0。您必须调整服务器上的PHP版本

<configuration>
    <system.webServer>
        <handlers>
            <remove name="PHP55_via_FastCGI" />
            <add name="PHP55_via_FastCGI" path="*.php" verb="GET,HEAD,POST" type="" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.5\php-cgi.exe" resourceType="Either" requireAccess="Script" allowPathInfo="true" preCondition="" responseBufferLimit="0" />
        </handlers>
        <urlCompression doDynamicCompression="false"/>
    </system.webServer>
</configuration>