【问题标题】:"Transfer-Encoding: chunked" header in PHPPHP中的“Transfer-Encoding:chunked”标头
【发布时间】:2011-06-16 03:17:35
【问题描述】:

我想将Transfer-Encoding: chunked 标头添加到我正在输出的文件中(它刚刚生成的纯文本),但是当我添加时:

header("Transfer-Encoding: chunked");
flush();

浏览器不想打开文件。

位于 ... 的网页可能是 暂时下降或可能已经移动 永久转移到一个新的网址。

我需要做什么才能让它工作?

【问题讨论】:

  • 您是否还发送了Content-Length 标头?
  • 不,您不应包含 Content-Length 标头。 Transfer-Encoding: chunked 的全部意义在于您的内容是动态生成的,因此您不知道先验的内容长度,因此无法设置此标头。

标签: php http header


【解决方案1】:

您需要在发送的每个块中发送Content-Length。看看Wikipedia 的第一印象,分块编码的样子。它不是那么微不足道,而且在许多情况下它的尺寸过大。

更新: 首先,您发送标头,因为它们必须始终在任何内容之前发送(也使用分块编码)。然后你发送(对于每个块)大小(十六进制),然后是内容。在每个块之后记住flush()。最后,您必须发送一个大小为零的块以确保连接正确关闭。

它没有经过测试,但是是这样的

header("Transfer-Encoding: chunked");
echo "5\r\n";
echo "Hello";
echo "\r\n\r\n";
flush();
echo "5\r\n";
echo "World";
echo "\r\n";
flush();
echo "0\r\n\r\n";
flush();

【讨论】:

  • 真的没必要考虑,除非你必须发送一些MB的内容。但是,我将使用基本说明更新我的答案
  • 以及如何将文本转换成块?例如,如果我的输出是 Hello_World_:)
  • 这个问题没有多大意义......一个块是一段内容,你定义为一段内容。这个想法是,你有一个长时间运行的脚本,它会产生很多数据。您可以不时将其中一些数据发送给客户端以节省内存并让客户端在等待时有事可做;)在您的情况下(Hello_World_:)),您当然可以将此字符串拆分成块,但这确实没有意义。
  • 我不是专家,但我认为这个答案可能是错误的。这些都不符合这里的答案:stackoverflow.com/questions/2481858/…。除非我有误解,否则 PHP 和 apache 会处理低级编码(输出块大小),因此您实际需要做的就是在输出结束前一次或多次刷新(),并且响应将分块传输编码。这符合我在 Firefox 中查看结果的经验(结果逐渐加载)
【解决方案2】:

正如之前的成员所说,您必须遵循分块传输编码格式。
在下一个示例中,我将展示如何使用一个用户函数来遵循格式规则:

<?php
//set headers
header('Transfer-Encoding: chunked');
header('Content-Type: text/html');

//browsers collect first 1024 bytes
//and show page only if bytes collected
//so we will use space padding.
//if you cannot understand what it means
//check script with PADDING=0
define("PADDING", 16);

//caret return and new line characters as constant
define("RN", "\r\n");

//user function what get current output buffer data
//and prefixes it with current buffer length.
//next it call flush functions
function flush_data(){
    $str=ob_get_contents();
    ob_clean();
    echo dechex(strlen($str)).RN.$str.RN;
    ob_flush();
    flush();
}

//default HTML 5 page
echo "<!doctype html><html><head><title>Transfer-Encoding: chunked</title>";
echo "<script>";

//+padding
for($i=0;$i<PADDING;$i++){
    //64 spaces (1 block)
    echo "                                                                ";
}
echo "</script></head><body><div>";

//current output buffer will shown immediately in browser
//after this function
flush_data();

//cycle wait 1 sec before next iteration
for($i=0;$i<5;$i++)
{
    //print iteration number
    echo "$i<br>";
    flush_data();
    sleep(1);
}

echo "</div></body></html>".RN;

//terminating part of encoding format
flush_data();
echo "0\r\n\r\n";
ob_flush();
?>

注意事项

  1. 检查 php.ini 中的 «implicit_flush» 是否为 On
  2. 知道如果您溢出输出缓冲区(php.ini 中的«output_buffering»),它将自动刷新。

【讨论】:

    【解决方案3】:

    对我来说,当我尝试使用“Transfer-Encoding: chunked”时,我必须使用此代码才能使其工作:

    <?php
    
    
    echo "data";
    header_remove("Transfer-Encoding"); 
    flush();
    
    ?>
    

    此代码仍将具有“Transfer-Encoding: chunked”标头。

    当你使用flush时它会自动设置Transfer-Encoding标题,但是当它手动设置时它会失败,所以为了防止出现任何问题,请尝试将其删除。还要确保在第一次刷新之前删除行上的标题以防止错误。

    【讨论】:

      【解决方案4】:

      flush();之前使用ob_flush();

      示例代码:

      <?php
              header('Content-Encoding', 'chunked');
              header('Transfer-Encoding', 'chunked');
              header('Content-Type', 'text/html');
              header('Connection', 'keep-alive');
      
              ob_flush();
              flush();
      
              $p = "";  //padding
              for ($i=0; $i < 1024; $i++) { 
                  $p .= " ";
              };
              echo $p;
      
              ob_flush();
              flush();
      
              for ($i = 0; $i < 10000; $i++) {
                  echo "string";
                  ob_flush();
                  flush();
                  sleep(2);
              }
      
      ?>
      

      【讨论】:

        猜你喜欢
        • 2015-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-09
        • 2017-10-03
        • 2020-04-17
        • 2014-03-30
        相关资源
        最近更新 更多