代码之家  ›  专栏  ›  技术社区  ›  Tom Smykowski

如何正确处理分块编码请求?

  •  3
  • Tom Smykowski  · 技术社区  · 15 年前

    我有两个网站:一个是带有PHP的Lighttpd,另一个是Apache,这两个网站都不能正确处理分块传输编码。

    我从我的手机J2ME发送这个请求,不可能将此传输类型更改为任何其他类型。

    所以我唯一的方法就是用另一种方式处理分块传输编码的请求。任何解决方案都是好的,只要我能在CentOS服务器上启用它,在那里我可以安装和更改所有必要的东西。

    所以我的问题是:如何在服务器端正确处理分块编码请求?

    1 回复  |  直到 15 年前
        1
  •  5
  •   Viper_Sb    15 年前

    编辑: 您正在运行哪个版本的PHP/Apache/LightHTTP?就像以前一样 this bug 在PHP之前,但是5.2.13和5.3.2似乎已经过时了。

    如果上面的链接没有帮助,我想知道PHP到底看到了什么,你能把这个放到api中并发布结果吗(当然了)。

    $input = file_get_contents('php://input');
    $stdin = file_get_contents('php://stdin');
    
    print "FILES: ";
    print_r($_FILES);
    
    print("<br>POST: ");
    print_r($_POST);
    
    print("<br>input: ".$input);
    print("<br>stdin: ".$stdin);
    die;
    

    结束编辑(留下下面的,以防别人发现有用)

    几年前我写过这个,它从一个分块的编码流中读取,然后你可以对输出做任何你想做的事情。如果是一个大文件,不要将其读入字符串,而是写入文件。

    <?php
    define('CRLF', "\r\n");
    define('BUFFER_LENGTH', 8192);
    $headers = '';
    $body = '';
    $length = 0;
    
    $fp = fsockopen($host, $port, $errno, $errstr, $timeout);
    
    // get headers FIRST
    do
    {
        // use fgets() not fread(), fgets stops reading at first newline
        // or buffer which ever one is reached first
        $data = fgets($fp, BUFFER_LENGTH);
        // a sincle CRLF indicates end of headers
        if ($data === false || $data == CRLF || feof($fp)) {
            // break BEFORE OUTPUT
            break;
        }
        $headers .= $data;
    }
    while (true);
    // end of headers
    
    // read from chunked stream
    // loop though the stream
    do
    {
        // NOTE: for chunked encoding to work properly make sure
        // there is NOTHING (besides newlines) before the first hexlength
    
        // get the line which has the length of this chunk (use fgets here)
        $line = fgets($fp, BUFFER_LENGTH);
    
        // if it's only a newline this normally means it's read
        // the total amount of data requested minus the newline
        // continue to next loop to make sure we're done
        if ($line == CRLF) {
            continue;
        }
    
        // the length of the block is sent in hex decode it then loop through
        // that much data get the length
        // NOTE: hexdec() ignores all non hexadecimal chars it finds
        $length = hexdec($line);
    
        if (!is_int($length)) {
            trigger_error('Most likely not chunked encoding', E_USER_ERROR);
        }
    
        // zero is sent when at the end of the chunks
        // or the end of the stream or error
        if ($line === false || $length < 1 || feof($fp)) {
            // break out of the streams loop
            break;
        }
    
        // loop though the chunk
        do
        {
            // read $length amount of data
            // (use fread here)
            $data = fread($fp, $length);
    
            // remove the amount received from the total length on the next loop
            // it'll attempt to read that much less data
            $length -= strlen($data);
    
            // PRINT out directly
            #print $data;
            #flush();
            // you could also save it directly to a file here
    
            // store in string for later use
            $body .= $data;
    
            // zero or less or end of connection break
            if ($length <= 0 || feof($fp))
            {
                // break out of the chunk loop
                break;
            }
        }
        while (true);
        // end of chunk loop
    }
    while (true);
    // end of stream loop
    
    // $body and $headers should contain your stream data
    ?>
    
    推荐文章