Search code examples
phppositionfreadfseek

php first fseek in stream then fread?


I am experimenting with some php file / stream functionality. And i am having troubles with fread.

This data is send to a php script:

    baz=bomb&foo=bar&baz=bomb&foo=bar&foo=bar&baz=bomb

And that script runs this code:

    <php
    $fp = fopen("php://input", "rb");
    fseek($fp, 3, SEEK_SET);
    echo "<br>ftell: ".ftell($fp)."<br>";
    echo "<br>fread(resource, 4): ".fread($fp, 4)."<br>";
    fclose($fp);

The output shows:

    ftell: 3
    fread(resource, 4): baz=

What i am expecting that it shows is:

    =bom

Why does it seem like fread sets the pointer to the beginning of the stream first and then reads? What is the point of seeking trough a stream and not being able to read from a certain position?

The php version i am using is: 7.0.8 on a windows machine.


Solution

  • This is the answer to the problem and i hope many will profit from this:

    When using fseek, ftell seems to tell you where the pointer is in the stream. But it isn't. The pointer in the stream isn't moveable by the fseek function strange enough. This is, as Starson Hochschild pointed out because the underlying stream does not implement the seek handler.

    So an alternative could be reading $_POST. But what about large content?

    There is a stream called php://temp. The first two MB you put in it will go into the ram of your pc. More data will go into a temporary file on your pc.

    So you could use that something like this:

        $tempStream = fopen("php://input", "rb");
        $stream = fopen("php://temp", "w+b");
        $size = 0;
        while (!feof($in)) $size += fwrite($stream,fread($tempStream,8192)); //Copy the php://input stream to the seekable php://temp stream. $size will contain the size in bytes of the $stream resource.
        fclose($tempStream);
    
        //Do your next fread's, fseek's, ftell's etc here on the $stream resource.
    
        fclose($stream);