it-swarm.com.de

Verwenden Sie Laravel, um die Tabelle als CSV herunterzuladen

Ich versuche, eine Datenbanktabelle mit Laravel als csv-Datei zu exportieren. Ich möchte, dass der Benutzer die Schaltfläche Export as CSV auswählen und die Tabelle als csv-Datei herunterladen kann. Momentan habe ich diesen Code bekommen, aber er funktioniert nicht:

mein Knopf:

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

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

Es gibt mir diesen Fehler zurück:

 The file "Resource id #154" does not exist

Und ich habe festgestellt, dass es so ist, weil versucht wird, eine Datei herunterzuladen, die nicht existiert. Gibt es eine alternative Möglichkeit, meinen Code zu ändern, um ihn als csv herunterzuladen. 

32
Javacadabra

Fast alles ist gut, außer dieser Zeile:

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

Sie sollten diese Zeile ändern in:

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

Ich bin hier gestolpert und habe versucht zu sehen, ob Laravel standardmäßig etwas eingebaut hat - die Antworten auf diese Frage machen mir etwas Sorgen. Ich stimme @ andré-daniel zu, dass die richtige Methode darin besteht, nicht zuerst eine Datei zu schreiben, sondern seine Implementierung die Werte manuell zusammenstellt. Dies würde fehlschlagen, wenn ein Wert Anführungszeichen, Leerzeichen usw. enthält.

Dies ist eine robustere Lösung, die Laravels Response::stream und phps fputcsv verwendet, um jede Zeile richtig zu formatieren (durch Anführungszeichen und notwendige Zeichenfolgen ersetzt. Siehe http://php.net/manual/de/function.fputcsv.php für 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);
}
57
Erik

EDIT: Siehe diese Antwort für eine bessere Lösung; Ich halte meine Antwort unten. Beachten Sie jedoch, dass bei der Generierung großer Dateien Probleme auftreten, beispielsweise Werte zu umgehen und unnötigen Speicherplatz zu verwenden.

Sie erstellen unnötigerweise eine Datei auf der Festplatte. Dies führt zu einer Festplatte IO und verursacht Probleme, wenn zwei Personen zur gleichen Zeit diese URL anfordern (zwei Instanzen des Frameworks schreiben in dieselbe Datei, und es kommt zu schlechten Dingen, z Ausnahme).

Verwenden Sie stattdessen diese:

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

Bis auf diese Zeile sieht alles gut aus: 

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

$handle zeigt nicht auf den korrekten Dateipfad. Es sollte beispielsweise der vollständige Pfad zu tweets.csv sein:

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

wobei $file so etwas wie $file = '/path/to/download/tweets.csv' sein sollte

1
virtuexru

Hier ist der vollständige Code zum Herunterladen von 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

Ich folgte diesen Beispielen und keines arbeitete für meinen Code. Ich füge den Code, den ich für mein Projekt geschrieben habe, als Beispiel hinzu. Das OP wird hier nicht angesprochen, nur als Beispiel. Meine Daten haben die Form eines Arrays von Objekten

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

Wenn Sie auf meiner return-Anweisung bemerkt haben, schließe ich -> send () ein, das die csv-Datei generiert und den Download initialisiert. Where as -> sendContent (); Legt einfach das Datum auf dem Bildschirm ab. Wenn Sie in diesem Beitrag auf dasselbe Problem stoßen, bei dem ich die Datei nicht heruntergeladen habe, lesen Sie unbedingt die offizielle Dokumentation.

https://api.symfony.com/2.3/Symfony/Component/HttpFoundation/StreamedResponse.html

0
jeremiah

Betrachten Sie die aktuell am besten bewertete Antwort Dies ist der CSV-Schreibvorgang von Laravel 5.7, beachten Sie die return-Änderungen.

<?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

versuche dies

 $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