【问题标题】:Output streaming with PHP ob_start & ob_get_clean使用 PHP ob_start 和 ob_get_clean 输出流式传输
【发布时间】:2014-06-08 04:50:51
【问题描述】:

我有一个脚本,echo 输出 php 脚本中的内容并生成一个非常大的文件,例如100MB

目前我使用以下方式捕获输出并写入另一个文件

ob_start();
require_once 'dynamic_data.php'; // echo 100MB data
$data = ob_get_clean();
file_put_contents($path, $data);

有什么简单的方法可以重写上面的程序(最好不要碰dynamic_data.php,因为它很难重构),这样它就可以直接将输出流式传输到文件而不将内容保存在内存中?

【问题讨论】:

  • 你不能直接在dymanic_data.php 中添加文件操作而不是回显和重新捕获输出而不回显吗?这样做有什么限制吗?
  • 因为使用 PHP 作为模板语言而不是直接打印到文件更容易循环/回显。此外,我可以将相同的脚本重复用于 Web 输出。

标签: php ob-start ob-get-contents


【解决方案1】:

ob_start documentation 提供了一个解决方法。您需要传入$output_callback$chunk_size

假设您将 $chunk_size 设置为 1MB。然后每缓冲 1MB 的输出数据,您的 $output_callback 将使用此数据调用,您可以将其刷新到磁盘(同时隐式刷新输出缓冲区)。

$output_callback = function($data) {
   //$buffer contains our 1MB of output

   file_put_contents($path, $data);

   //return new string buffer
   return "";
}

//call $output_callback every 1MB of output buffered.
ob_start($output_callback, 1048576);

require_once 'dynamic_data.php';

//call ob_clean at the end to get any remaining bytes 
//(implicitly calls $output_callback final time)
ob_clean();

【讨论】:

    【解决方案2】:

    您可以使用proc_open 并使用此文件作为参数调用PHP 解释器。这不会将数据存储在内存中,但会创建另一个进程。

    $descriptorspec = array(
       0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
       1 => array("file", $path, "w"),  // stdout is a pipe that the child will write to
       2 => array("file", $path, "a") // stderr is a file to write to
    );
    
    $process = proc_open('php dynamic_data.php', $descriptorspec, $pipes);
    
    if (is_resource($process)) {
        // $pipes now looks like this:
        // 0 => writeable handle connected to child stdin
        // 1 => readable handle connected to child stdout
        // Any error output will be appended to /tmp/error-output.txt
    
        fclose($pipes[0]);
        fclose($pipes[1]);
        $return_value = proc_close($process);
    }
    ?>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      • 2018-08-01
      • 1970-01-01
      • 2011-10-18
      • 2016-12-02
      相关资源
      最近更新 更多