Mathieu De Keyzer's face

 Stream a CSV from a JSON array

HTTP enthusiasts

Goal

Stream a CSV from an array of string array with Symfony.

Solution

    /**
     * @param $string[][] $table
     */
    public function csvResponse(array $table, string $filename = 'csv_export', string $disposition = 'attachment'): StreamedResponse
    {

        $response = new StreamedResponse(
            function () use ($table) {
                $handle = \fopen('php://output', 'r+');
                if (false === $handle) {
                    throw new \RuntimeException('Unexpected error while opening php://output');
                }

                foreach ($table as $row) {
                    \fputcsv($handle, $row);
                }
            }
        );

        $response->headers->set('Content-Type', 'text/csv; charset=utf-8');
        $response->headers->set('Content-Disposition', \sprintf('%s;filename="%s.csv"', $disposition, $filename));
        $response->headers->set('Cache-Control', 'max-age=0');
        
        return $response;
    }

Explanation

Stream a response avoid to:

  • delay the response once the CSV is generated
  • load in memory the data in CSV format or generate a tempory file with the response

In this example I'm using the Symfony Symfony\Component\HttpFoundation\StreamedResponse class. It works with a callback function. Every things streamed to the standard output inside that callback will be pushed to the stream response.

At line 10 I open the file php://output, it's a write-only stream that allows you to write to the standard output buffer. It's how I push in the output stream. Indeed, to convert an array of string into a CSV line I use the fputcsv function. As that function requires a file pointer I can't just stream directly to the standard output.

You see that I set those 3 headers:

  • Content-Type without the browser won'tunderstand that is a text file
  • Content-Disposition specify the filename and if the file must be downladed (attachment) or can be shown in the browser (inline)
  • Cache-Control specify if te response can be cahced or not