Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Laravel to Download table as CSV

I am trying to export a database table using Laravel as a csv file. I would like the user to be able to select the Export as CSV button and download the table as a csv file. Currently I've gotten this code but It is not working:

my button:

<a href="/all-tweets-csv" class="btn btn-primary">Export as CSV</a> 

my route:

Route::get('/all-tweets-csv', function(){      $table = Tweet::all();     $filename = "tweets.csv";     $handle = fopen($filename, 'w+');     fputcsv($handle, array('tweet text', 'screen name', 'name', 'created at'));      foreach($table as $row) {         fputcsv($handle, array($row['tweet_text'], $row['screen_name'], $row['name'], $row['created_at']));     }      fclose($handle);      $headers = array(         'Content-Type' => 'text/csv',     );      return Response::download($handle, 'tweets.csv', $headers); }); 

It returns me this error:

 The file "Resource id #154" does not exist 

And I've gathered that it is because it is trying to download a file that does not exist. Is there an alternative way I can go about modifying my code in order to download as a csv.

like image 846
Javacadabra Avatar asked Oct 01 '14 17:10

Javacadabra


2 Answers

I stumbled in here trying to see if Laravel had something built in by default - the answers for this question worry me a bit. I agree with @andré-daniel that the proper method is to not write a file first, but his implementation is manually putting together the values, which would fail if any value contained quotes, spaces, etc.

This is a more robust solution, using Laravel's Response::stream and php's fputcsv to format each line properly (will escape quotes, and quote necessary strings. see http://php.net/manual/en/function.fputcsv.php for details)

<?php  public function download() {     $headers = [             'Cache-Control'       => 'must-revalidate, post-check=0, pre-check=0'         ,   'Content-type'        => 'text/csv'         ,   'Content-Disposition' => 'attachment; filename=galleries.csv'         ,   'Expires'             => '0'         ,   'Pragma'              => 'public'     ];      $list = User::all()->toArray();      # add headers for each column in the CSV download     array_unshift($list, array_keys($list[0]));     $callback = function() use ($list)      {         $FH = fopen('php://output', 'w');         foreach ($list as $row) {              fputcsv($FH, $row);         }         fclose($FH);     };      return response()->stream($callback, 200, $headers) } 
like image 105
Erik Avatar answered Oct 11 '22 14:10

Erik


Almost everything is fine except this line:

return Response::download($handle, 'tweets.csv', $headers); 

You should change this line into:

return Response::download($filename, 'tweets.csv', $headers); 
like image 28
Marcin Nabiałek Avatar answered Oct 11 '22 14:10

Marcin Nabiałek