web-dev-qa-db-fra.com

Utilisez Laravel pour télécharger le tableau au format CSV

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

32
Javacadabra

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);
25
Marcin Nabiałek

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);
}
57
Erik

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);
});
15
user2629998

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);

$file devrait être quelque chose comme $file = '/path/to/download/tweets.csv'

1
virtuexru

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);
1
M Arfan

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

0
jeremiah

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();
}
0
Joshua

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');
0
Tejendra Pareek