Search code examples
phpput

stream_copy_to_stream never finishes


I'm trying to save text to a file that was sent in a PUT request. This is basically the code I use (based on the documentation):

    $content = fopen("php://stdin", "r");
    $fp = fopen($this->getFileName(), "w");
    stream_copy_to_stream($content, $fp);

    fclose($fp);
    fclose($content);

Whenever I try to PUT something to this script, it just runs forever. Using the debugger I found the problem to be in stream_copy_to_stream - the script runs fine up to this point but it never reaches the lines where it closes the resources.

What am I doing wrong here?


Solution

  • This is because the stdin stream never closes and the third parameter to stream_copy_to_stram, is set by default to read an unlimited number of bytes.

    <?php 
    $reader = fopen("php://stdin", "r");
    $writer = fopen("test.out", "w");
    stream_copy_to_stream($reader, $writer);
    
    fclose($reader);
    fclose($writer);
    

    Try running this from the command line.

    // at this point it will block forever waiting on stdin
    $ php reader_writer.php
    Type something 
    ^C
    

    The string "Type Something" will be written to the file.

    To fix this, you can rewrite as:

    $reader = fopen("php://input", "r");
    $writer = fopen("test.out", "w");
    while ($line = fgets($reader)) {
        fwrite($writer, $line, strlen($line));
    }
    
    fclose($reader);
    fclose($writer);
    

    As an interesting side note in PHP 5.6 php://input is reusable

    Or when on the command line.

    $reader = fopen("php://stdin", "r");
    $writer = fopen("test.out", "w");
    while ($line = fgets($reader)) {
        fwrite($writer, $line, strlen($line));
    }
    fclose($reader);
    fclose($writer);
    

    Then run

    $ echo "sdfsdaf" | php read_write.php