J'essaie d'exporter une table de base de données en utilisant Laravel
en tant que fichier csv
. J'aimerais que l'utilisateur puisse sélectionner le bouton Export as CSV
et télécharger le tableau sous la forme d'un fichier csv
. Actuellement, j'ai ce code mais il ne fonctionne pas:
mon bouton:
<a href="/all-tweets-csv" class="btn btn-primary">Export as CSV</a>
mon itinéraire:
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);
});
Cela me renvoie cette erreur:
The file "Resource id #154" does not exist
Et j'ai compris que c'était parce qu'il essayait de télécharger un fichier qui n'existe pas. Existe-t-il un moyen alternatif de modifier mon code afin de le télécharger en tant que csv
.
Presque tout va bien sauf cette ligne:
return Response::download($handle, 'tweets.csv', $headers);
Vous devriez changer cette ligne en:
return Response::download($filename, 'tweets.csv', $headers);
Je suis tombé par hasard ici pour essayer de voir si Laravel avait quelque chose d'intégré par défaut - les réponses à cette question m'inquiètent un peu. Je suis d'accord avec @ andré-daniel sur le fait que la bonne méthode consiste à ne pas écrire un fichier au préalable, mais son implémentation consiste à assembler manuellement les valeurs, ce qui échouerait si une valeur contenait des guillemets, des espaces, etc.
Ceci est une solution plus robuste, utilisant les codes Response::stream
de Laravel et fputcsv
de php pour formater chaque ligne correctement (échappera les guillemets et les chaînes nécessaires. Voir http://php.net/manual/en/function.fputcsv.php pour plus de détails)
<?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: voir cette réponse pour une meilleure solution; Je garderai ma réponse ci-dessous, mais notons qu'il existe des problèmes tels que le fait de ne pas échapper de valeurs et d'utiliser une quantité de mémoire déraisonnable lors de la génération de gros fichiers.
Vous créez inutilement un fichier sur le disque; cela induit un disque IO et causera des problèmes si deux personnes demandent cette adresse URL exactement au même moment exception).
Utilisez ceci à la place:
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);
});
Tout a l'air bien sauf cette ligne:
return Response::download($handle, 'tweets.csv', $headers);
$handle
ne pointe pas vers le chemin de fichier correct. Ce doit être le chemin complet de tweets.csv, par exemple:
return Response::download($file, 'tweets.csv', $headers);
où $file
devrait être quelque chose comme $file = '/path/to/download/tweets.csv'
Voici le code complet pour télécharger 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);
Je suivais ces exemples et aucun d’entre eux ne travaillait pour mon code. Je joins le code que j'ai écrit pour mon projet à titre d'exemple. Cela ne concerne pas le PO, mais simplement à titre d'exemple. Mes données sont sous la forme d'un tableau d'objets
public function Export($data) {
$headers = array(
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=summary.csv",
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0"
);
$columns = array('Period', 'RevenueArea', 'Subs');
$callback = function() use ($data, $columns)
{
$file = fopen('php://output', 'w');
fputcsv($file, $columns);
foreach($data as $items) {
fputcsv($file, array($items->PERIOD, $items->REVENUE_AREA, $items->SUBS));
}
fclose($file);
};
return Response::stream($callback, 200, $headers)->send();
}
Si vous avez remarqué sur ma déclaration de retour, j'inclus -> send () qui génère le fichier csv et initialise le téléchargement. Où as -> sendContent (); affiche la date à l’écran. Si vous tombez sur cet article avec le même problème que le téléchargement du fichier que j'ai eu, assurez-vous de vérifier la documentation officielle.
https://api.symfony.com/2.3/Symfony/Component/HttpFoundation/StreamedResponse.html
Considérant la réponse actuellement la mieux classée il s’agit de l’écriture Laravel 5.7 CSV, notez les changements return
.
<?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 (new StreamedResponse($callback, 200, $headers))->sendContent();
}
essaye ça
$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');