Я пытаюсь экспортировать таблицу базы данных, используя Laravel
в качестве файла csv
. Я хотел бы, чтобы пользователь мог выбрать кнопку « Export as CSV
и загрузить таблицу в виде файла csv
. В настоящее время я получил этот код, но он не работает:
моя кнопка:
<a href="/all-tweets-csv" class="btn btn-primary">Export as CSV</a>
мой маршрут:
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); });
Он возвращает мне эту ошибку:
The file "Resource id #154" does not exist
И я понял, что это потому, что он пытается загрузить файл, который не существует. Есть ли альтернативный способ, по которому я могу изменить свой код, чтобы загрузить его как csv
.
Почти все прекрасно, за исключением этой строки:
return Response::download($handle, 'tweets.csv', $headers);
Вы должны изменить эту строку на:
return Response::download($filename, 'tweets.csv', $headers);
Я наткнулся на это, пытаясь понять, есть ли у Laravel что-то построенное по умолчанию – ответы на этот вопрос меня немного беспокоят. Я согласен с @ andré-daniel, что правильный метод состоит в том, чтобы не писать файл сначала, но его реализация вручную объединяет значения, которые не сработают, если какое-либо значение содержит кавычки, пробелы и т. Д.
Это более надежное решение, использующее Laporvel's Response::stream
и php fputcsv
для правильной форматирования каждой строки ( fputcsv
кавычки и укажите необходимые строки. См. http://php.net/manual/en/function.fputcsv.php для Детали)
<?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); }
EDIT: см. Этот ответ для лучшего решения; Я сохраню свой ответ ниже, но заметьте, что у него есть такие проблемы, как не ускользание значений и использование необоснованных объемов памяти при генерации больших файлов.
Вы произвольно создаете файл на диске; который вызывает диск IO и вызывает проблемы, если два человека запросят этот URL-адрес в одно и то же время (два экземпляра фреймворка будут писать в тот же файл, и произойдет плохой материал, например, служение поврежденному файлу или сбой с исключением).
Используйте это вместо этого:
Route::get('/all-tweets-csv', function() { $tweets = Tweets::all(); // the csv file with the first row $output = implode(",", array('tweet text', 'screen name', 'name', 'created at')); foreach ($tweets as $row) { // iterate over each tweet and add it to the csv $output .= implode(",", array($row['tweet_text'], $row['screen_name'], $row['name'], $row['created_at'])); // append each row } // headers used to make the file "downloadable", we set them manually // since we can't use Laravel's Response::download() function $headers = array( 'Content-Type' => 'text/csv', 'Content-Disposition' => 'attachment; filename="tweets.csv"', ); // our response, this will be equivalent to your download() but // without using a local file return Response::make(rtrim($output, "\n"), 200, $headers); });
Вот полный код для загрузки CSV
$headers = array( 'Content-Type' => 'application/vnd.ms-excel; charset=utf-8', 'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0', 'Content-Disposition' => 'attachment; filename=abc.csv', 'Expires' => '0', 'Pragma' => 'public', ); $filename = "doenload.csv"; $handle = fopen($filename, 'w'); fputcsv($handle, [ "id", "name", }); DB::table("tablename")->chunk(100, function($data) use($handle) { foreach ($data as $row) { // Add a new row with data fputcsv($handle, [ $row->id, $row->name, }); fclose($handle); return Response::download($filename, "download.csv", $headers);
Все выглядит хорошо, за исключением этой строки:
return Response::download($handle, 'tweets.csv', $headers);
$handle
не указывает на правильный путь к файлу. Это должен быть полный путь к tweets.csv, например:
return Response::download($file, 'tweets.csv', $headers);
где $file
должен быть чем-то вроде $file = '/path/to/download/tweets.csv'
public function export() { $people = Person::all(); $csv = \League\Csv\Writer::createFromFileObject(new \SplTempFileObject()); $csv->insertOne(\Schema::getColumnListing('people')); foreach ($people as $person) { $csv->insertOne($person->toArray()); } $csv->output('people.csv'); }
попробуй это
$file_name = "abc"; $postStudent = Input::all(); $ck = DB::table('loan_tags')->select('LAN')->where('liabilitiesId', $postStudent['id'])->get(); $i = 0; foreach ($ck as $row) { $apps[$i]['LAN'] = $row->LAN; $apps[$i]['Account_number'] = $postStudent['account_number']; $apps[$i]['Bank_Name'] = $postStudent['bank_name']; $i++; } ob_end_clean(); ob_start(); Excel::create($file_name, function($excel) use($apps){ $excel->sheet('Sheetname', function($sheet) use($apps){ $sheet->row(1, array( 'LAN', 'Account number' , 'Bank Name' )); $k = 2; foreach ($apps as $deta) { $sheet->row($k, array($deta['LAN'], $deta['Account_number'], $deta['Bank_Name'] )); $k++; } }); })->download('xlsx');