我有一个ob_start()
和一个对应的ob_flush()
. 我想刷新一部分数据并继续执行其余部分。使用ob_flush()
没有帮助。此外,如果可能需要休息而不显示浏览器中的加载。
编辑:
我不想使用ajax
我有一个ob_start()
和一个对应的ob_flush()
. 我想刷新一部分数据并继续执行其余部分。使用ob_flush()
没有帮助。此外,如果可能需要休息而不显示浏览器中的加载。
编辑:
我不想使用ajax
我过去曾这样做过,这就是我解决它的方法:
ob_start();
/*
* Generate your output here
*/
// Ignore connection-closing by the client/user
ignore_user_abort(true);
// Set your timelimit to a length long enough for your script to run,
// but not so long it will bog down your server in case multiple versions run
// or this script get's in an endless loop.
if (
!ini_get('safe_mode')
&& strpos(ini_get('disable_functions'), 'set_time_limit') === FALSE
){
set_time_limit(60);
}
// Get your output and send it to the client
$content = ob_get_contents(); // Get the content of the output buffer
ob_end_clean(); // Close current output buffer
$len = strlen($content); // Get the length
header('Connection: close'); // Tell the client to close connection
header("Content-Length: $len"); // Close connection after $len characters
echo $content; // Output content
flush(); // Force php-output-cache to flush to browser.
// See caveats below.
// Optional: kill all other output buffering
while (ob_get_level() > 0) {
ob_end_clean();
}
正如我之前在几条评论中所说,你应该注意压缩你的内容,因为这会改变你的内容的长度,但不会改变它的标题。它还可以缓冲您的输出,因此不会立即发送到客户端。
您可以尝试让 apache 知道不要使用 gzip 压缩您的内容apache_setenv('no-gzip', '1');
。但是,如果您使用重写规则转到您的页面,这将不起作用,因为它也会修改这些环境变量。至少,它对我来说是这样的。
请参阅手册中有关将内容刷新给用户的更多注意事项。
ob_flush
写入缓冲区。换句话说,ob_flush
告诉 PHP 给 Apache(或 nginx/lighttpd/whatever)输出,然后让 PHP 忘记它。一旦 Apache 有了输出,它就可以随心所欲地使用它。(换句话说,在ob_flush
您无法控制它是否立即写入浏览器之后)。
所以,简短的回答:没有保证的方法可以做到这一点。
只是猜测,您可能正在寻找 AJAX。每当人们试图操纵页面内容加载时,AJAX 几乎总是正确的路径。
如果您想在后台继续执行任务,可以使用ignore_user_abort
,如此处详述,但是,这通常不是最佳方法。您基本上失去了对该线程的控制,在我看来,Web 服务器线程不属于繁重的处理。
我会尝试从面向网络的东西中提取它。这可能意味着一个 cron 条目或只是从 PHP 内部生成一个后台进程(虽然从脚本执行内部开始的进程不会随着脚本而死,并且脚本不会等待它在死前完成)。
如果你真的走那条路,这意味着你甚至可以在必要时制作某种身份系统。然后,您可以监控执行情况并定期向用户提供进度更新。(从技术上讲,您也可以使用 -ed 脚本制作状态系统ignore_user_abort
,但它对我来说似乎并不干净。)
这是我的功能
function bg_process($fn, $arr) {
$call = function($fn, $arr){
header('Connection: close');
header('Content-length: '.ob_get_length());
ob_flush();
flush();
call_user_func_array($fn, $arr);
};
register_shutdown_function($call, $fn, $arr);
}
最后包装要执行的函数,在php关闭连接之后。当然浏览器会停止缓冲。
function test() {
while (true) {
echo 'this text will never seen by user';
}
}
这是调用函数的方法
bg_process('test');
第一个参数是callable
,第二个参数是要传递给带有索引数组的“测试”函数的数组
注意:我不在ob_start()
脚本开头使用。
我有一篇文章解释了如何在我的博客上使用 apache/mod_php 来实现这一点:http: //codehackit.blogspot.com/2011/07/how-to-kill-http-connection-and.html希望这会有所帮助,干杯
fastcgi_finish_request
此函数将所有响应数据刷新到客户端并完成请求。这允许在不打开与客户端的连接的情况下执行耗时的任务。
不能在 Apache 上工作。(PHP 5 >= 5.3.3,PHP 7)
如果您使用的是 PHP-FPM:
ignore_user_abort(true);
fastcgi_finish_request();
以上两个功能是ignore_user_abort
防止错误和fastcgi_finish_request
关闭客户端连接的关键因素。
采用:
header("Content-Length: $len");
..where$len
是要刷新到客户端的数据的长度。
我没有背景知道这将在何时何地起作用,但我尝试了一些浏览器,并立即返回:
<?PHP
header("Content-length:5");
echo "this is more than 5";
sleep(5);
?>
编辑:Chrome、IE 和 Opera 显示this
,而 FireFox 显示this is more than 5
。在那之后,他们所有人都关闭了请求。