Output 5Mb JSON error: slim/slim/Slim/Http/Stream.php on line 385

I have an application with Slim Framework (v3) and there is a method that needs output a (not so) large JSON. It’s about 5Mb.

In my server it goes quite well, but in my local environment it leads to an error:

Warning: fwrite(): Unable to create temporary file, Check permissions in temporary files directory. slim/slim/Slim/Http/Stream.php on line 385

That file/method writes the content to the http stream. I presume PHP’s memory_limit was the problem, but no matter I increase the value, the error still there.

The method in that file looks like this:

/**
 * Write data to the stream.
 *
 * @param string $string The string that is to be written.
 *
 * @return int Returns the number of bytes written to the stream.
 *
 * @throws RuntimeException on failure.
 */
public function write($string)
{
    //var_dump($string); // -> shows the correct big JSON
    //var_dump($this->isWritable()); // -> evaluates to TRUE
    //die(); 
    if (!$this->isWritable() || ($written = fwrite($this->stream, $string)) === false) {
        throw new RuntimeException('Could not write to stream');
    }

    // reset size so that it will be recalculated on next call to getSize()
    $this->size = null;

    return $written;
}

The “var_dump and die” outputs the correct JSON. The $this->isWritable() evaluates to TRUE. The problem is at $written = fwrite($this->stream, $string).

Probably it’s related to my local PHP configurations, but I can not figure it out. OR maybe I should use a different approach inside Slim, and not just $response->withJson($result). I saw some posts about Stream a big file, but I am trying avoid write the String to a file and stream the file in the response. Maybe there is better way of doing this.

Any help is much appreciated.

This is probably related to the use of php://temp, which is used by default by Slim for streams inthe constructor of Slim\Http\Response. As stated in the php docs:

php://memory and php://temp are read-write streams that allow temporary data to be stored in a file-like wrapper. The only difference between the two is that php://memory will always store its data in memory, whereas php://temp will use a temporary file once the amount of data stored hits a predefined limit (the default is 2 MB). The location of this temporary file is determined in the same way as the sys_get_temp_dir() function.

Because of the treshold of 2Mb you won’t run into this problem with most other requests.

To solve this, you can either assign file write permissions to the web server user on the temporary folder or you can use php://memory to avoid the creation of the temporary file:

    $fh = fopen('php://memory', 'rw');
    $stream = new Slim\Http\Stream($fh);

    $stream->write(json_encode(['test' => 'test value']));

    return $response->withBody($stream);