我有一个php脚本,可以通过验证从csv文件导入大量数据 为此,我需要向用户显示进度。我已经使用Event Streaming了。
当我回应一些东西时,我希望它一个接一个地转移到客户端而不是服务器批量发送整个输出。
我已经玩过ob_start(),ob_implicit_flush()& ob_flush(),但它们不起作用。
我的脚本在另一台服务器上工作得很好。 下面给出了服务器配置:
代码未按要求响应的服务器配置,即
OS: Linux PHP Version 5.4.36-0+deb7u3 Server API: CGI/FastCGI Memory_limit: 128M output_buffering: no value
正如我所说,代码在另一台具有几乎相同配置的服务器上正常工作,即
OS: Linux PHP Version 5.4.37 Server API: CGI/FastCGI Memory_limit: 256MB output_buffering: no value
以下是我发送活动的示例代码:
<?php
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
header("Access-Control-Allow-Origin: *");
$lastEventId = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0);
if ($lastEventId == 0) {
$lastEventId = floatval(isset($_GET["lastEventId"]) ? $_GET["lastEventId"] : 0);
}
echo ":" . str_repeat(" ", 2048) . "\n"; // 2 kB padding for IE
echo "retry: 2000\n";
// event-stream
$i = $lastEventId;
while ($i <= 100) {
if($i==100){
echo "data: stop\n";
ob_flush();
flush();
break;
} else {
echo "id: " . $i . "\n";
echo "data: " . $i . ";\n\n";
ob_flush();
flush();
sleep(1);
}
$i++;
}
?>
以下是我需要回复的客户页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>EventSource example</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="../jquery/eventsource.js"></script>
<script>
var es = new EventSource("events.php");
var listener = function(event) {
console.log(event.data);
var type = event.type;
if (event.data == 'stop') {
es.close();
} else {
var div = document.createElement("div");
div.appendChild(document.createTextNode(type + ": " + (type === "message" ? event.data : es.url)));
document.body.appendChild(div);
}
};
var errlistener = function(event) {
es.close();
}
es.addEventListener("open", listener);
es.addEventListener("message", listener);
es.addEventListener("error", errlistener);
</script>
</head>
<body>
</body>
</html>
答案 0 :(得分:6)
将隐藏数据返回浏览器的最佳方法是使用Web套接字让客户端打开文件读取器的套接字,然后就可以将数据块化到浏览器而不会出现问题。
一旦完成,你可以关闭套接字。
一个很好的Web套接字教程
RabbitMQ
使用这种方法,如果你想要实现验证,那么服务器不只是发送块,而是按照javascript的请求发送块。
所以你的客户可以说我需要块5,你的服务器实现类似
的东西$requestedChunk = 5; // this would be set by the javascript sending the request
$chunkSize = 256; // this would be your chunk size;
$readPossition = $requestedChunk * $chunkSize;
Link不再有用,所以这里有一个基于Ratchet:http://www.phpbuilder.com/articles/application-architecture/optimization/creating-real-time-applications-with-php-and-websockets.html
答案 1 :(得分:0)
我有类似的问题。事件流在使用Apache 2.0处理程序的服务器上按预期工作(返回块),但不在使用FastCGI的服务器上(返回批量处理)。我认为FastCGI中的某些东西是罪魁祸首,因此试图通过切换到CGI来解决问题。现在,事件流按预期工作。
无论是使用CGI还是FastCGI,Server API都显示为CGI / FastCGI,因此我假设它为您运行的服务器正在运行CGI,而它运行的服务器正在运行FastCGI。尝试将非工作服务器更改为CGI。
至于为什么它在FastCGI中不起作用我并不完全确定,但除非它是必要的要求且CGI不可能,否则上述解决方案应该有效。
答案 2 :(得分:0)
许多事情可以防止分块响应,例如但不限于;
你应该先检查这些。