[PHP] csv - Datei zum download generieren

(Bier)Kelle

BackRoad Fahrer
ID: 1297
L
28 April 2006
6.828
507
Hi Folks,

ich hab mir nen kleines Adressbüchlein geschrieben.
Sind ein paar PHP Skripte mit ner MySQL Datenbank im Hintergrund.

Wie stelle ich es jetzt an, dass man alle Einträge als csv Datei über den browser exportieren kann?

gruss kelle!
 
Schicke folgende Header, das löst den Download-Mechanismus beim Browser aus:
PHP:
$csvdata="...."; // <- hier die csv-Daten rein
header("content-type: application/csv-tab-delimited-table");
header("content-length: ".strlen($csvdata));
header("content-disposition: attachment; filename=\"filename.csv\"");
echo $csvdata;
Wegen Content-Type musst du probieren, den hab ich nur auf die Schnelle ergooglet. Man findet auch text/csv. Keine Ahnung, welcher richtig is und mit welchem es richtig funktioniert.
Da einfach ausprobieren. Wichtig is content-disposition, damit der Browser die Ausgabe als Datei downloaden will.
 
Normal ausgeben, nur entsprechende header senden. (Guck da mal nach Content-Disposition und sowas. Wenn ich mich richtig erinnere, gab es da allerdings ein paar Inkompatibilitäten mit verschiedenen Browsern.)
 
Ich habs so gemacht wie Hacker beschrieben...
Auf meinem Testsystem zu Hause funzt es einwandfrei, auf den Produktivserver geladen, und schon klappts nicht mehr...

PHP:
<?php
	header("content-type: application/csv-tab-delimited-table");
	header("content-length: ".strlen($csvdata));
	header("content-disposition: attachment; filename=\"adressliste.csv\"");
	$connection = mysql_connect("localhost", "user", "passwd");
	mysql_select_db("db", $connection);
	$result = mysql_query ("SELECT * FROM book", $connection);
	echo mysql_error();
	$csvdata="TESTEINTRAG";
	while ($row = mysql_fetch_array($result))
	{
		$csvdata = $csvdata.$row["name"].";";
		$csvdata = $csvdata.$row["first_name"].";";
		$csvdata = $csvdata.$row["strasse"].";";
		$csvdata = $csvdata.$row["plz"].";";
		$csvdata = $csvdata.$row["ort"].";";
		$csvdata = $csvdata.$row["geburtstag"].";";
		$csvdata = $csvdata.$row["tel_priv"].";";
		$csvdata = $csvdata.$row["tel_dienst"].";";
		$csvdata = $csvdata.$row["handy"].";";
		$csvdata = $csvdata.$row["email_1"].";";
		$csvdata = $csvdata.$row["email_2"].";\n";
	}
	echo $csvdata; 
?>

Die Datei wird komplett leer runtergeladen, selbst der Testeintrag wird ignoriert, also am SQL Teil kanns eigentlich nicht liegen...

gruss kelle!
 
flaschenkind schrieb:
Du überschreibst $csvdata aber immer. Der letze Wert ist wohl leer^^
Nimm .=

a) Überschreib ich nix, ich hänge nur an
b) was meinst Du mit .=
c) slebst ein explizietes belegen der Variable $csvdata vor dem echo hat keinerlei Auswirkung

gruss kelle!
 
Kelle schrieb:
a) Überschreib ich nix, ich hänge nur an
b) was meinst Du mit .=
c) slebst ein explizietes belegen der Variable $csvdata vor dem echo hat keinerlei Auswirkung

gruss kelle!
a/b)
Habe mich vertan, ist schon richtig. Mit .= ist das etwas einfacher, dann würde das so aussehen:
$csvdata .= $row["name"].";";
anstatt
$csvdata = $csvdata.$row["name"].";";
 
PHP:
header("content-length: ".strlen($csvdata));
sendet
Code:
[COLOR=#000000][COLOR=#dd0000]content-length: 0[/COLOR][/COLOR]
an den Clienten ;)

Du darfst den Header erst schicken, wenn du die Länge des Inhalts kennst. Allerdings muss der Header vor dem Inhalt gesendet werden.
 
Kelle schrieb:
Klingt soweit logisch, nur wie umgehe ich jetzt das Problem?
siehe mein erster Post (#2):
Genier erst den Content, dann "mess" seine Länge, danach hau die HTTP-Header an den Clienten raus und erst zum Schluss jag den Content hinterher.
 
Na das soll mir jetzt mal einer erklären...
Mein Apache meckert rum, wenn der Header nicht ganz oben steht, der Apache von all-inkl meckert da nicht...

Was hab ich wieder verdreht?

gruss kelle!
 
Das müsste so aussehen:

PHP:
<?php
    $connection = mysql_connect("localhost", "user", "passwd");
    mysql_select_db("db", $connection);
    $result = mysql_query ("SELECT * FROM book", $connection);
    echo mysql_error();
    $csvdata="TESTEINTRAG";
    while ($row = mysql_fetch_array($result))
    {
        $csvdata = $csvdata.$row["name"].";";
        $csvdata = $csvdata.$row["first_name"].";";
        $csvdata = $csvdata.$row["strasse"].";";
        $csvdata = $csvdata.$row["plz"].";";
        $csvdata = $csvdata.$row["ort"].";";
        $csvdata = $csvdata.$row["geburtstag"].";";
        $csvdata = $csvdata.$row["tel_priv"].";";
        $csvdata = $csvdata.$row["tel_dienst"].";";
        $csvdata = $csvdata.$row["handy"].";";
        $csvdata = $csvdata.$row["email_1"].";";
        $csvdata = $csvdata.$row["email_2"].";\n";
    }
    header("content-type: application/csv-tab-delimited-table");
    header("content-length: ".strlen($csvdata));

    header("content-disposition: attachment; filename=\"adressliste.csv\"");

    echo $csvdata;
?>
 
Kelle schrieb:
Mein Apache meckert rum, wenn der Header nicht ganz oben steht, der Apache von all-inkl meckert da nicht...
Der Apache meckert immer rum, wenn du nach dem Content einen Header schicken willst.
Dass das nie einer versteht, wie HTTP funktioniert :-?

Wenn auch nur ein Byte Content draußen is, darf kein Header mehr geschickt werden, weil der in der Ausgabe oben sein muss. Wo der Header im Script gesendet wird, kriegt doch der Webserver nicht mit.

Bsp:
PHP:
// Ok, wenn in bla() nichts ausgegeben wird
bla();
bla();
header("test: valid");
echo "content";
PHP:
// Nicht ok, da vor dem Header Content gesendet wurde
echo "content1";
header("test: invalid");
echo "content2";