PHP:关闭输出流

时间:2012-01-23 20:13:29

标签: php http-headers outputstream

是否可以关闭PHP脚本的输出流?我有一个脚本需要做一些后期处理,但在后期处理期间和之后它不再向客户端发送任何数据,所以我想在后期处理之前关闭连接。

编辑:在我的应用程序中,我有一个需要不时重建的缓存。但是,我不想让用户放慢速度。我想要的是在脚本的最后确定是否需要重建缓存。所以我想首先关闭输出流,以便用户获取它的数据,然后我想重建缓存。这样做并不是非常关键,但我认为最好先关闭连接,这样用户就不会注意到缓存正在重建,如果这需要很长时间。

3 个答案:

答案 0 :(得分:5)

<强>更新

处理这种情况的方法是输出缓冲和适当的HTTP标头的组合。

来自HTTP/1.1 Specification Section 14.10

  

HTTP / 1.1为发件人定义“关闭”连接选项   表示连接完成后将关闭   响应。

因此,除了 Connection:close 之外,如果我们传递HTTP Content-Length 标头,浏览器知道在收到指定的响应长度后关闭连接:

  1. 缓冲所有脚本输出,以便保留发送标题的功能
  2. 获得完整的输出数据后,将相应的标题发送到客户端
  3. 继续处理...但不要尝试发送输出,否则会因为标题已发送而收到错误。
  4. 另外,请注意,如果进行过多处理,可以在Web服务器SAPI中遇到脚本执行时间限制。最后,您应该告诉PHP使用ignore_user_abort()忽略此特定脚本中的“用户中止”,因为浏览器将因您正在执行的操作而关闭连接,并且您希望PHP继续处理。

    <?php
    ignore_user_abort();
    ob_start();
    
    // do stuff, generate output
    
    // get size of the content
    $length = ob_get_length();
    
    // tell client to close the connection after $length bytes received
    header('Connection: close');
    header("Content-Length: $length");
    
    // flush all output
    ob_end_flush();
    ob_flush();
    flush();
    
    // close session if you have one ...
    // continue your processing tasks ...
    ?>
    

    您可以查看Connection handlingdocs上的PHP手册部分。

    或者,为什么不开始输出缓冲?然后,您可以捕获将要发送的所有输出,然后在您确实想要对其执行任何操作时稍后决定。

    <?php
    
    echo 'before output buffering';
    ob_start();
    echo 'after output buffering';
    $output = ob_get_contents();
    
    // script's only output to this point will be 'before output buffering'
    
    // I changed my mind, send the output ...
    ob_end_flush();
    ?>
    

答案 1 :(得分:0)

答案 2 :(得分:0)

我没有足够的声誉来发表评论,但我想在@rdlowrey回答中分享 gzip 可能是个问题。

如果您启用了 gzip ,则传输编码标头始终设置为 chunked ,即使您尝试使用{{ 1}}因此它不会发送 Content-Length 标题。

我能解决这个问题的方法是使用下一个:

header("Transfer-encoding: none");

然后是解决方案:

<?
@ini_set('zlib.output_compression', 'Off');
@ini_set('output_buffering', 'Off');
@ini_set('output_handler', '');
@apache_setenv('no-gzip', 1);
?>