“Transfer-Encoding: chunked” header in PHP

2020-01-29 10:36发布

问题:

i want to add Transfer-Encoding: chunked header to the file that i'm outputing (its just generated plain text), but when i add:

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

the browser doesn't want to open the file.

The webpage at ... might be temporarily down or it may have moved permanently to a new web address.

what i need to do for it to work?

回答1:

You need to send the Content-Length with every chunk you send. Look at Wikipedia for a first impression, how a chunked encoding looks like. Its not that trivial and in many cases its oversized.

Update: First you send the headers, because they must always send before any content (also with chunked encoding). Then you send (for every chunk) the size (in hexadecimal) followed by the content. Remember flush() after every chunk. At last you must send a zero-size chunk to make sure, that the connection get closed properly.

Its not tested, but something like this

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


回答2:

As previous members said you have to follow chunked transfer encoding format.
In next example i will show how you can use one user function to follow format rules:

<?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();
?>

Notes:

  1. Check if «implicit_flush» is On in your php.ini
  2. Know if you overflow output buffer («output_buffering» in php.ini) it will flush automatically.


回答3:

For me when I was trying something with "Transfer-Encoding: chunked" I had to use this code to make it work:

<?php


echo "data";
header_remove("Transfer-Encoding"); 
flush();

?>

This code will still have the "Transfer-Encoding: chunked" header.

It automatically sets the Transfer-Encoding heading when you use flush but when it set it manually it fails, so to prevent any problems try to remove it. Also make sure that you remove the heading on the line before you do your first flush to prevent errors.



回答4:

Use ob_flush(); before flush();

Sample code:

<?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);
        }

?>


标签: php http header