How to Stream Data in PHP

How to Stream Data in PHP

Takahiro Iwasa
Takahiro Iwasa
2 min read

PHP can stream response using php://output, which can be useful for handling large data.

php://output is a write-only stream that allows you to write to the output buffer mechanism in the same way as print and echo.

PHP 7.1 Example

Here is a short example which allows users to download CSV files. The key points are fopen('php://output', 'w'); which opens a stream.



namespace App\Lib\Stream;

 * Class DownloadStream
 * @package App\Lib\Stream
class DownloadStream
    public static function getStream(string $fileName)
        // Send header
        header("Content-Type: application/octet-stream");
        header("Content-Disposition: attachment; filename={$fileName}");

        // Get output stream
        $stream = fopen('php://output', 'w');

        // Filter to conver character code to ShiftJIS
        stream_filter_prepend($stream, 'convert.iconv.utf-8/cp932');
        // Filter to convert newline to CRLF
        stream_filter_register('CrlfFilter', 'App\Lib\Stream\Filter\CrlfFilter');
        stream_filter_append($stream, 'CrlfFilter');

        return $stream;


This is a stream filter to convert line ending into CRLF. Although this is not directly relevant to streaming data, it would be useful for Windows users.


namespace App\Lib\Stream\Filter;

 * Class CrlfFilter
 * @package App\Lib\Stream\Filter
class CrlfFilter extends \php_user_filter
     * Callback method when this filter is applied
     * @param resource $in
     * @param resource $out
     * @param int $consumed
     * @param bool $closing
     * @return int
    public function filter($in, $out, &$consumed, $closing)
        while ($bucket = stream_bucket_make_writeable($in)) {
            // Clear newline codes in advance
            $bucket->data = preg_replace("/\r$/", "", $bucket->data);
            $bucket->data = preg_replace("/\n$/", "", $bucket->data);
            // Append CRLF
            $bucket->data = $bucket->data . "\r\n";

            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        return PSFS_PASS_ON;


Here is an example usage.

// Filename
$fileName = 'test.csv';

// Get download stream
$stream = DownloadStream::getStream($fileName);

// Output header
fputcsv($stream, [

// Output record
fputcsv($stream, [
    'ABC Company',

// Close stream


If you want to implement a feature such as downloading a CSV file containing one million records, you can use php://output.

I hope you will find this post useful.

Takahiro Iwasa

Takahiro Iwasa

Software Developer at KAKEHASHI Inc.
Involved in the requirements definition, design, and development of cloud-native applications using AWS. Now, building a new prescription data collection platform at KAKEHASHI Inc. Japan AWS Top Engineers 2020-2023.