How to make PHP generate Chunked response

后端 未结 9 2055
渐次进展
渐次进展 2020-11-28 06:32

I googled for this problem but there is no answer for it.

I want my PHP script to generate HTTP response in chunked( http://en.wikipedia.org/wiki/Chunked_transfer_en

相关标签:
9条回答
  • 2020-11-28 07:02

    Working sample as of 16.02.2013

    <?php
    
    function dump_chunk($chunk) {
        //echo sprintf("%x\r\n", strlen($chunk));
        echo sprintf("\r\n");
        echo $chunk;
        echo "\r\n";
    }
    
    ob_start();
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Title</title>
        </head>
        <body>
            <?php
            ob_end_flush();
            flush();
            ob_flush();
            for ($i = 0; $i < 5; $i++) {
                sleep(1);
                dump_chunk('Sending data chunk ' . ($i + 1) . ' of 1000 <br />');
                flush();
                ob_flush();
            }
            sleep(1); // needed for last animation
            ?>
        </body>
    </html>
    
    0 讨论(0)
  • 2020-11-28 07:09

    Andriy F.'s solution worked for me. Here's a simplified version of his answer:

    function dump_chunk($chunk)
    {
        echo $chunk;
        flush();
        ob_flush();
    }
    
    header('Content-Type: text/html; charset=UTF-8');
    
    flush();
    
    for ($i = 0; $i < 3; $i++) {
        dump_chunk('Sending data chunk ' . ($i + 1) . ' of 1000 <br />');
        sleep(1);
    }
    

    Although I don't understand why the ob_flush() call is needed. If someone knows, please comment.

    0 讨论(0)
  • 2020-11-28 07:10

    This has gotten a little vauge... if you don't mind big assed chunks, (0x1000 octets or so), then yes, PHP will make them.

    <?php
    
    while (true) {
        # output data
        flush()
        usleep(pow(2,18));
    }
    ?>
    

    PHP will generated the numbered sections, etc.

    If you want to send tiny little chunks, as you might do with an AJAX client... well, I've combined the OPs question, with some research on PHP.NET, and it does look like he was on to a good thing.

    $ echo -en "GET /chunked/ HTTP/1.1\r\nHost: ec\r\n\r\n" | nc localhost 80

    HTTP/1.1 200 OK
    Date: Wed, 23 May 2012 13:03:01 GMT
    Server: Apache/2.2.9 (Debian) PHP/5.3.5-1 with Suhosin-Patch mod_ssl/2.2.9 OpenSSL/0.9.8o
    X-Powered-By: PHP/5.3.5-1
    Transfer-encoding: chunked
    Content-Type: text/html
    
    14
    Teachers have class.
    50
    We secure our friends not by accepting favors but by doing them.
                -- Thucydides
    48
    Vulcans never bluff.
                -- Spock, "The Doomsday Machine", stardate 4202.1
    31
    All kings is mostly rapscallions.
                -- Mark Twain
    41
    Reappraisal, n.:
        An abrupt change of mind after being found out.
    49
    He who knows, does not speak.  He who speaks, does not know.
                -- Lao Tsu
    

    Whether or not it will eventually squeeze out it out's own (incorrect) chunk count, remains to be seen... but I saw no sign of it.

    <?php
    header("Transfer-encoding: chunked");
    @apache_setenv('no-gzip', 1);
    @ini_set('zlib.output_compression', 0);
    @ini_set('implicit_flush', 1);
    for ($i = 0; $i < ob_get_level(); $i++)  ob_end_flush();
    ob_implicit_flush(1); flush();
    
    function dump_chunk($chunk)
    {
      printf("%x\r\n%s\r\n", strlen($chunk), $chunk);
      flush();
    }
    
    for (;;) {
      $output = array();
      exec("/usr/games/fortune", $output);
      dump_chunk(implode("\n", $output));
      usleep(pow(2,18));
    }
    ?>
    
    0 讨论(0)
  • 2020-11-28 07:11

    You should be able to use:

    <?php header("Transfer-Encoding: chunked");
    

    but you'll have to ensure yourself that the output follows the specifications.

    0 讨论(0)
  • I needed to do two additional things to get this to work. Call ob_start if an object had not yet been started. And also echo out a long empty string. The browser requires a certain amount of content to be sent in it's first chunk it appears.

    header('Content-Encoding', 'chunked');
    header('Transfer-Encoding', 'chunked');
    header('Content-Type', 'text/html');
    header('Connection', 'keep-alive');
    
    if (ob_get_level() == 0) ob_start();
    echo str_pad('',4096)."\n";
    ob_flush();
    flush();
    
    0 讨论(0)
  • 2020-11-28 07:18

    The output buffer will not be sent to the browser until it is full. The default size is 4096 bytes. So you either need to change the buffer size or pad your chunks. Also, the browser may have it's own minimum buffer before the page is displayed. Note that according to the Wikipedia Article about chunked encoding, sending a 0\r\n\r\n chunk terminates the response.

    If you want to change the output buffering size setting, I read that you cannot use ini_set('output_buffering', $value). Instead, change the output buffering setting by adding the following to your php.ini file.

    php_value output_buffering 1024
    

    Here's an example of padding your chunks

    header("Transfer-Encoding: chunked");
    header("Content-Encoding: none");
    
    // Send chunk to browser
    function send_chunk($chunk)
    {
        // The chunk must fill the output buffer or php won't send it
        $chunk = str_pad($chunk, 4096);
    
        printf("%x\r\n%s\r\n", strlen($chunk), $chunk);
        flush();
    }
    
    // Send your content in chunks
    for($i=0; $i<10; $i++)
    {
        send_chunk("This is Chunk #$i.<br>\r\n");
        usleep(500000);
    }
    
    // note that if you send an empty chunk
    // the browser won't display additional output
    echo "0\r\n\r\n";
    flush();
    

    Here's a short version that demonstrates 0\r\n\r\n\ terminating the output:

    $output = "hello world";
    header("Transfer-Encoding: chunked");
    header('Content-Encoding: none');
    printf("%x\r\n%s\r\n", strlen($output), $output);
    ob_flush();
    print("0\r\n\r\n");
    ob_flush();
    flush();
    sleep(10);
    print('POST PROCESSING');
    
    0 讨论(0)
提交回复
热议问题