Matthew Smart Matthew Smart - 2 months ago 40
PHP Question

CSV export in laravel 5 controller

So I have made a little ajax request to my

reviewsController@export
.

Now when I
console.log()
the data in my success method, the ajax response shows the correct data. However my CSV has not downloaded. So I have all the right info and have created the csv essentially.

I think this has possibly to do with setting the headers maybe?

public function export()
{
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");

$reviews = Reviews::getReviewExport($this->hw->healthwatchID)->get();
$columns = array('ReviewID', 'Provider', 'Title', 'Review', 'Location', 'Created', 'Anonymous', 'Escalate', 'Rating', 'Name');

$file = fopen('php://output', 'w');
fputcsv($file, $columns);

foreach($reviews as $review) {
fputcsv($file, array($review->reviewID,$review->provider,$review->title,$review->review,$review->location,$review->review_created,$review->anon,$review->escalate,$review->rating,$review->name));
}
exit();
}


Is there anything I am doing wrong here, or does Laravel have something to cater for this?

Answer

Try this version out - this should allow you to get a nice output using Response::stream().

public function export()
{
    $headers = array(
        "Content-type" => "text/csv",
        "Content-Disposition" => "attachment; filename=file.csv",
        "Pragma" => "no-cache",
        "Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
        "Expires" => "0"
    );

    $reviews = Reviews::getReviewExport($this->hw->healthwatchID)->get();
    $columns = array('ReviewID', 'Provider', 'Title', 'Review', 'Location', 'Created', 'Anonymous', 'Escalate', 'Rating', 'Name');

    $callback = function() use ($reviews, $columns)
    {
        $file = fopen('php://output', 'w');
        fputcsv($file, $columns);

        foreach($reviews as $review) {
            fputcsv($file, array($review->reviewID,$review->provider,$review->title,$review->review,$review->location,$review->review_created,$review->anon,$review->escalate,$review->rating,$review->name));
        }
        fclose();
    };
    return Response::stream($callback, 200, $headers);
}

(Adapted from this SO answer: Use Laravel to Download table as CSV)

Try using a regular link with target="_blank" rather than using JavaScript/AJAX. Because it's a file download opening in a new tab, the user experience shouldn't be too clunky.