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

发布于 2024-07-14 19:57:04 字数 289 浏览 12 评论 0原文

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

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

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

echo $content;
?>

上述问题:

  • 客户端在渲染整个页面之前不会收到任何
  • 内容文件可能很大,所以我宁愿不在内存中保存整个内容

任何建议?

So, I'm looking for something more efficient than this:

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

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

echo $content;
?>

The problems with the above:

  • Client doesn't receive anything until the entire page is rendered
  • File might be enormous, so I'd rather not have the whole thing in memory

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雅心素梦 2024-07-21 19:57:04

有趣的问题; 我认为我以前没有尝试过解决这个问题。

我认为您需要从前端 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);
?>

Interesting problem; don't think I've tried to solve this before.

I'm thinking you'll need to have a second request going from your front-facing PHP script to your server. This could be a simple call to http://localhost/test.php. If you use fopen-wrappers, you could use fread() to pull the output of test.php as it is rendered, and after each chunk is received, output it to the screen and append it to your test.html file.

Here's how that might look (untested!):

<?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);
?>
千里故人稀 2024-07-21 19:57:04

更好的方法是使用 ob_start 接受的前两个参数:output_callback 和 chunk_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 的输出流,则可以返回空字符串。

A better way to do this is to use the first two parameters accepted by ob_start: output_callback and chunk_size. The former specifies a callback to handle output as it's buffered, and the latter specifies the size of the chunks of output to handle.

Here's an example:

$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);

In this example, the output buffer will be flushed (sent) for every 4096 bytes of output (and once more at the end by the ob_end_flush call). Each time the buffer is flushed, the callback $write_ob_to_file will be called and passed the latest chunk. This gets written to test.html. The callback then returns false, meaning "output this chunk as is". If you wanted to only write the output to file and not to PHP's output stream, you could return an empty string instead.

满身野味 2024-07-21 19:57:04

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

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

Pix0r's answer is what you want unless you actually need it "included" rather than just executed. For example, if you have login information before the test.php, it will not get passed into the file if you call it with fopen.

If you need it genuinely included, then what you have is the simplest method, but if you want constant output, you'll need to actually write test.php in a manner that outputs as well as stores the information as it goes. As far as I know there's no way to both collect buffer and output it as you go.

可是我不能没有你 2024-07-21 19:57:04

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

Here you go x-send-file, use mod_xsendfile to send file efficiently, really easy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文