将输出流式传输到文件和浏览器

时间:2009-03-06 16:49:12

标签: php caching output-buffering

所以,我正在寻找比这更有效的东西:

<?php
ob_start();
include 'test.php';
$content = ob_get_contents();

file_put_contents('test.html', $content);

echo $content;
?>

上述问题:

  • 在呈现整个页面之前,客户端不会收到任何内容
  • 文件可能很庞大,所以我宁愿不把整件事记在内存中

有什么建议吗?

4 个答案:

答案 0 :(得分:6)

有趣的问题;不要以为我以前试过解决这个问题。

我认为你需要从你面向前面的PHP脚本到服务器的第二个请求。这可以是对http://localhost/test.php的简单调用。如果你使用fopen-wrappers,你可以使用fread()在渲染时拉取test.php的输出,并在收到每个块后,将它输出到屏幕并将其附加到你的test.html文件。

这是看起来如何(未经测试!):

<?php
$remote_fp = fopen("http://localhost/test.php", "r");
$local_fp = fopen("test.html", "w");
while ($buf = fread($remote_fp, 1024)) {
    echo $buf;
    fwrite($local_fp, $buf);
}
fclose($remote_fp);
fclose($local_fp);
?>

答案 1 :(得分:2)

更好的方法是使用ob_startoutput_callbackchunk_size接受的前两个参数。前者指定一个回调来处理缓冲的输出,后者指定要处理的输出块的大小。

以下是一个例子:

$output_file = fopen('test.html', 'w');
if ($output_file === false) {
    // Handle error
}

$write_ob_to_file = function($buffer) use ($output_file) {
    fwrite($output_file, $buffer);

    // Output string as-is
    return false;
};

ob_start($write_ob_to_file, 4096);
include 'test.php';
ob_end_flush();

fclose($output_file);

在此示例中,将为每4096个字节的输出刷新(发送)输出缓冲区(并在ob_end_flush调用结束时再次刷新(发送))。每次刷新缓冲区时,都会调用回调$write_ob_to_file并传递最新的块。这将写入test.html。然后回调返回false,意思是“按原样输出此块”。如果您只想将输出写入文件而不是PHP的输出流,则可以返回空字符串。

答案 2 :(得分:0)

Pix0r的答案就是你想要的,除非你真的需要它“包含”而不是仅仅执行。例如,如果你在test.php之前有登录信息,那么如果用fopen调用它就不会传入文件。

如果你需要真正包含它,那么你所拥有的是最简单的方法,但是如果你想要恒定的输出,你需要以输出的方式实际编写test.php,并在信息存储时存储信息。 。据我所知,没有办法收集缓冲区并输出它。

答案 3 :(得分:-1)

这里你去x-send-file,使用mod_xsendfile高效地发送文件,非常简单。