Wie erstelle und lade ich eine CSV-Datei aus dem PHP-Skript herunter?

86

Ich bin ein Anfänger im Programmieren und habe viel nach meiner Frage gesucht, aber keine hilfreiche Lösung oder ein Tutorial dazu gefunden.

Mein Ziel ist es, ein PHP-Array zu haben und die Array-Elemente werden in einer Liste auf der Seite angezeigt.

Ich möchte eine Option hinzufügen, damit ein Benutzer, wenn er möchte, eine CSV-Datei mit Array-Elementen erstellen und herunterladen kann.

Ich weiß nicht, wie ich das machen soll. Ich habe auch viel gesucht. Aber noch keine hilfreiche Ressource zu finden.

Bitte geben Sie mir ein Tutorial oder eine Lösung oder einen Rat, um es selbst zu implementieren. Da ich ein Anfänger bin, bieten Sie bitte einfach zu implementierende Lösungen an.

Mein Array sieht aus wie:

Array
(
    [0] => Array
        (
            [fs_id] => 4c524d8abfc6ef3b201f489c
            [name] => restaurant
            [lat] => 40.702692
            [lng] => -74.012869
            [address] => new york
            [postalCode] => 
            [city] => NEW YORK
            [state] => ny
            [business_type] => BBQ Joint
            [url] => 
        )

)
user2302780
quelle
2
phpExcel für eine CSV-Datei ist ein bisschen zu viel .. php.net/manual/en/function.fputcsv.php
Damien Pirsy
Zeigen Sie Ihre Array - Struktur und I c ein liefern einige Code die Elemente in eine csv zu drehen
Halb schnell
@ halb schnell Ich habe die Array-Struktur in der Post hinzugefügt
user2302780
2
Wie kann der Spaltentitel in die CSV-Datei eingefügt werden?
user2302780
Mögliches Duplikat des Exports nach CSV über PHP
Michal Mau

Antworten:

198

Sie können das integrierte fputcsv () für Ihre Arrays verwenden, um korrekte CSV-Zeilen aus Ihrem Array zu generieren. Sie müssen also die Zeilen wie folgt durchlaufen und sammeln:

$f = fopen("tmp.csv", "w");
foreach ($array as $line) {
    fputcsv($f, $line);
}

Damit die Browser das Dialogfeld "Speichern unter" anbieten, müssen Sie HTTP-Header wie folgt senden (weitere Informationen zu diesem Header finden Sie im RFC ):

header('Content-Disposition: attachment; filename="filename.csv";');

Alles zusammen:

function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
    // open raw memory as file so no temp files needed, you might run out of memory though
    $f = fopen('php://memory', 'w'); 
    // loop over the input array
    foreach ($array as $line) { 
        // generate csv lines from the inner arrays
        fputcsv($f, $line, $delimiter); 
    }
    // reset the file pointer to the start of the file
    fseek($f, 0);
    // tell the browser it's going to be a csv file
    header('Content-Type: application/csv');
    // tell the browser we want to save it instead of displaying it
    header('Content-Disposition: attachment; filename="'.$filename.'";');
    // make php send the generated csv lines to the browser
    fpassthru($f);
}

Und Sie können es so verwenden:

array_to_csv_download(array(
  array(1,2,3,4), // this array is going to be the first row
  array(1,2,3,4)), // this array is going to be the second row
  "numbers.csv"
);

Update:
Anstelle von php://memorykönnen Sie auch das php://outputfür den Dateideskriptor verwenden und das Suchen und dergleichen abschaffen:

function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename="'.$filename.'";');

    // open the "output" stream
    // see http://www.php.net/manual/en/wrappers.php.php#refsect2-wrappers.php-unknown-unknown-unknown-descriptioq
    $f = fopen('php://output', 'w');

    foreach ($array as $line) {
        fputcsv($f, $line, $delimiter);
    }
}   
complex857
quelle
2
Warum nicht echodie generierten CSV-Zeilen direkt in der Schleife?
Alex Shesterov
1
@AlexShesterov, der Hauptgrund ist, dass fputcsv()die generierte Zeile nicht zurückgegeben wird, sondern ein Dateideskriptor zum Schreiben benötigt wird. Sie können den Puffer jedoch bei jeder Iteration zurückspulen, schreiben und löschen, wenn der Speicher eingeschränkt ist. Oder verwenden Sie stattdessen einfach eine echte temporäre Datei.
Komplex857
@ complex857 Wie kann ich einen Spaltentitel für die CSV hinzufügen?
user2302780
@ user2302780: Sie stellen Ihren Daten lediglich eine Zeile mit Spaltennamen voran. Sie können die Schlüssel aus den Datenfeldern mit so etwas wie$data = array_merge(array(array_keys($data[0])), $data);
complex857
1
@JoseRojas, das ist zu erwarten, da Sie, sobald Sie etwas über den Draht gelegt haben (was das Ausgeben von Dingen mit PHP konzeptionell bedeutet), nicht mehr darauf zurückkommen können. Zur Verwendung php://outputsiehe das zweite aktualisierte Codebeispiel.
Komplex857
17

Ich habe nicht genug Ruf, um auf die @ complex857-Lösung zu antworten. Es funktioniert großartig, aber ich musste hinzufügen; am Ende des Content-Disposition-Headers. Ohne diese Option fügt der Browser am Ende des Dateinamens zwei Bindestriche hinzu (z. B. wird anstelle von "export.csv" die Datei als "export.csv--" gespeichert). Wahrscheinlich wird versucht, \ r \ n am Ende der Kopfzeile zu bereinigen.

Die richtige Zeile sollte folgendermaßen aussehen:

header('Content-Disposition: attachment;filename="'.$filename.'";');

Falls in CSV UTF-8-Zeichen enthalten sind, müssen Sie die Codierung in UTF-8 ändern, indem Sie die Zeile Inhaltstyp ändern:

header('Content-Type: application/csv; charset=UTF-8');

Außerdem finde ich es eleganter, rewind () anstelle von fseek () zu verwenden:

rewind($f);

Vielen Dank für Ihre Lösung!

Luxian
quelle
2
Ich habe das --am Ende der Dateinamen noch nie selbst erlebt , aber ich habe die Antwort aktualisiert (warum nicht einfach eine Bearbeitung einreichen?)
complex857
13

Versuchen Sie ... CSV-Download.

<?php 
mysql_connect('hostname', 'username', 'password');
mysql_select_db('dbname');
$qry = mysql_query("SELECT * FROM tablename");
$data = "";
while($row = mysql_fetch_array($qry)) {
  $data .= $row['field1'].",".$row['field2'].",".$row['field3'].",".$row['field4']."\n";
}

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="filename.csv"');
echo $data; exit();
?>
Indrajeet Singh
quelle
wird brechen, wenn ein Feldwert enthält, deshalb bevorzuge ich tsv (Tab ist seltener als und wir können es ersetzen oder so)
oriadam
11

Das ist die Funktion, die ich für mein Projekt verwendet habe und die wie erwartet funktioniert.

function array_csv_download( $array, $filename = "export.csv", $delimiter=";" )
{
    header( 'Content-Type: application/csv' );
    header( 'Content-Disposition: attachment; filename="' . $filename . '";' );

    // clean output buffer
    ob_end_clean();

    $handle = fopen( 'php://output', 'w' );

    // use keys as column titles
    fputcsv( $handle, array_keys( $array['0'] ) );

    foreach ( $array as $value ) {
        fputcsv( $handle, $value , $delimiter );
    }

    fclose( $handle );

    // flush buffer
    ob_flush();

    // use exit to get rid of unexpected output afterward
    exit();
}
Sajidur Rahman
quelle
1
Es fiel mir schwer, es in WordPress send_headers hook zu implementieren, da jedes Mal, wenn alle aktuellen HTML-Seiten am Ende der CSV-Datei hinzugefügt werden. Diese Antworten halten mich sehr an, aber ich benutze sie ohne Pufferoperationen.
Oleg Apanovich
sauberer Ausgabepuffer löste für mich das Problem, dass vor der Verwendung dieser Codezeilen am Anfang und am Ende der gebildeten Datei leere Zeilen waren.
Sharunas Bielskis
8

Verwenden Sie den folgenden Code, um ein PHP-Array in CSV zu konvertieren

<?php
   $ROW=db_export_data();//Will return a php array
   header("Content-type: application/csv");
   header("Content-Disposition: attachment; filename=test.csv");
   $fp = fopen('php://output', 'w');

   foreach ($ROW as $row) {
        fputcsv($fp, $row);
   }
   fclose($fp);
Kiran Reddy
quelle
3

Wenn Ihre Array-Struktur immer genau so mehrdimensional ist, können wir die Elemente wie folgt durchlaufen:

$fh = fopen('somefile.csv', 'w') or die('Cannot open the file');

for( $i=0; $i<count($arr); $i++ ){
    $str = implode( ',', $arr[$i] );
    fwrite( $fh, $str );
    fwrite( $fh, "\n" );
}
fclose($fh);

Das ist eine Möglichkeit, dies zu tun ... Sie können es manuell tun, aber diese Möglichkeit ist schneller und einfacher zu verstehen und zu lesen.

Dann würden Sie Ihre Header etwas verwalten, was complex857 tut, um die Datei auszuspucken. Sie können die Datei dann mit unlink () löschen, wenn Sie sie nicht mehr benötigen, oder Sie können sie auf dem Server belassen, wenn Sie dies wünschen.

halbschnell
quelle
0

Verwenden Sie Folgendes:

echo "<script type='text/javascript'> window.location.href = '$file_name'; </script>";
Ashwin Balani
quelle