martincarlin87
martincarlin87

Reputation: 11042

Laravel: Generating and downloading a CSV file using StreamedResponse produces ERR_INVALID_RESPONSE

I have a controller method like so:

use Symfony\Component\HttpFoundation\StreamedResponse;

public function downloadTransactions($type)
{
    $this->authorize('download', Invoice::class);

    $filename = 'invoices-' . strtolower($type) . '.csv';

    $response = new StreamedResponse(function() {

        Invoice::generateTransactionsCsv($type);

    }, 200, [
        'Content-Type' => 'text/csv',
        'Content-Disposition' => 'attachment; filename="' . $filename . '"',
    ]);

    return $response;

}

and then in my Invoice model I am populating the file:

public static function generateTransactionsCsv($type = null)
{
    // Open output stream
    $handle = fopen('php://output', 'w');

    // Add CSV headers
    fputcsv($handle, [
        'ID',
        'REF',
        'DESCRIPTION',
        'DATE',
        'AMOUNT',
    ]);

    // Close the output stream
    fclose($handle);
}

but I get an ERR_INVALID_RESPONSE in Chrome, although I would assume the browser doesn't matter. I've checked similar questions which suggest installing the zip extension but I already have it installed. Using PHP 7.1 locally. Also tried looking at the logs but there doesn't seem to be anything there (using Valet locally).

If I move the logic from the model to the controller then it works fine but my example above is simplified to just the header row of the csv, in reality, there's a bit more to it so I'd like to keep the logic in the model if possible.

I've also tried opening and closing the file handle in the controller and passing it the model but that didn't work either.

Upvotes: 2

Views: 7113

Answers (1)

martincarlin87
martincarlin87

Reputation: 11042

Looks like it was because the $type variable wasn't being passed correctly:

$response = new StreamedResponse(function() use ($type) {
    ....
}

Was able to figure it out thanks to Safari, it downloaded a csv with the Laravel error trace in it which was weird, I didn't think it would be any different from Chrome.

Upvotes: 1

Related Questions