Stream Response

Normally, resources are rendered by renderers into one string and finally echoed out, but then you cannot output content whose size exceeds the memory limit of PHP. With StreamRenderer you can stream HTTP output and you can output large size content while keeping memory consumption low. Stream output can also be used in coexistence with existing renderers.

Change Transferer and Renderer

Use the StreamTransferInject trait on the page to render and respond to the stream output. In the example of this download page, since $body is made to be a resource variable of the stream, the injected renderer is ignored and the resource is streamed.

use BEAR\Streamer\StreamTransferInject;

class Download extends ResourceObject
{
    use StreamTransferInject;

    public $headers = [
        'Content-Type' => 'image/jpeg',
        'Content-Disposition' => 'attachment; filename="image.jpg"'
    ];

    public function onGet(): static
    {
        $fp = fopen(__DIR__ . '/BEAR.jpg', 'r');
        $this->body = $fp;

        return $this;
    }
}

With Renderers

Stream output can coexist with conventional renderers. Normally, Twig renderers and JSON renderers generate character strings, but when a stream is assigned to a part of it, the whole is output as a stream.

This is an example of assigning a string and a resource variable to the Twig template and generating a page of inline image.

Template

<!DOCTYPE html>
<html lang="en">
<body>
<p>Hello, {{ name }}</p>
<img src="data:image/jpg;base64,{{ image }}">
</body>
</html>

name assigns the string as usual, but assigns the resource variable of the image file’s pointer resource to image with the base64-encode filter.

class Image extends ResourceObject
{
    use StreamTransferInject;

    public function onGet(string $name = 'inline image'): static
    {
        $fp = fopen(__DIR__ . '/image.jpg', 'r');
        stream_filter_append($fp, 'convert.base64-encode'); // image base64 format
        $this->body = [
            'name' => $name,
            'image' => $fp
        ];

        return $this;
    }
}

If you want to further control streaming such as streaming bandwidth and timing control, uploading to the cloud, etc use StreamResponder which is build for it.

The demo is available at MyVendor.Stream.


This document needs to be proofread by native speaker.