PHP/MySQL - Header - Downloads
1. Die Abschnitte
- Erläuterung
- "Cannot modify ..."
- Pufferung
- Kleine Beispiele
- Internet Media Type
- Dateien
- Downloads
- Charset
- HTTP-Header
2. Zwang
Manchmal kann es passieren, dass man einen direkten Download erzwingen möchte. Ein wunderbares Beispiel dafür sind JPEG-Bilder, die im CMYK-Format abgespeichert worden sind. Denn damit kommen die meisten Browser nicht klar, da es vor allem im DTP-Bereich eingesetzt wird.
Bietet man also zum Beispiel eine Bilddatenbank mit CMYK-JPEGs an, so darf man die nicht einfach verlinken. Nein, man setzt einen Link auf
eine PHP-Datei, die dann die Arbeit übernimmt. Öffnet dazu im Ordner downloads
mal die Datei download.htm
.
Dort setzen wir den Anker mittels <a href="bilder_cmyk.php">Bild</a>
.
3. Der Download
... findet in der oben erwähnten bilder_cmyk.php
statt. Der Einfachheit halber arbeiten wir mal ohne GET-Parameter, sondern
nehmen einfach ein "hartkodiertes" Bild. Der Code selber sieht so aus:
<?php
$jpg = file_get_contents('moi_cmyk.jpg');
$size = filesize('moi_cmyk.jpg');
header('Content-Disposition: attachment; filename=moi_cmyk.jpg');
header('Content-type: application/force-download');
header('Content-Length: '.$size);
header('Content-type: application/octetstream');
echo $jpg;
?>
Erläuterung
Mit $jpg = file_get_contents('moi_cmyk.jpg');
lesen wir wie gehabt das Bild ein und mit $size =
filesize('moi_cmyk.jpg');
ermitteln wir die Dateigröße. Zu Letzterem komme ich später.
Den Download erzwingen
Das geschieht über header('Content-Disposition: attachment; filename=moi_cmyk.jpg');
. Allerdings führt das dazu, dass
bei einem vorgegebene Download-Verzeichnis (zum Beispiel im Firefox möglich) das Bild einfach dort abgespeichert wird. Mit
header('Content-type: application/force-download');
"zwingt" man den Browser dazu, ein entsprechendes Dialogfeld zu öffnen.
Das ist allerdings abhängig von den dortigen Einstellungen. So bietet Firefox zum Beispiel an, ob man die Datei speichern oder mit
einem entsprechenden Programm öffnen möchte.
Zusatzinfos
Bei größeren Dateien ist es immer ganz gut, wenn der Browser weiß, wie viel er herunterladen muss. Dann kann er nämlich die Download-Zeit
einigermaßen präzise berechnen. Und da wir die ja schon mit $size = filesize('moi_cmyk.jpg');
errechnet haben, senden wir
sie mittels header('Content-Length: '.$size);
.
Und was soll das header('Content-type: application/octetstream');
? Ist das nicht überflüssig? Eigentlich ja, aber das
ist eine der Merkwürdigkeiten, die uns immer wieder begegnen. Denn jeder Browser reagiert anders und manchmal muss man mit dezenten
Hinweisen oder roher Gewalt arbeiten, damit es auch so funktioniert, wie wir wollen. Obiger Code zum Beispiel war noch vor Jahren
nötig, damit der Internet Explorer für Mac(!) damit klar kam.
Leere Seite?
Viele Anfänger denken oft, dass bei einem Klick auf den Link erst die Seite bilder_cmyk.php
aufgerufen wird. Dann erscheint
eine leere Seite und dann kommt der Download-Dialog. Falsch! Zuerst sendet der Server die entsprechenden Header und
dann erst(!) entscheidet der Browser, wie er damit umgeht. In diesem Fall sagt er sich
"Kenn isch net, will isch net, fort damit" [Quelle: Ein Browser]
und überlässt dem Anwender die Entscheidung. Das bedeutet auch, dass er die angeforderte Seite bilder_cmyk.php
nicht im
Browserfenster lädt! Praktisch, gell?
4. Noch mehr Feinheiten
Bei obigem Beispiel mit einem CMYK-JPEG mussten wir schon etwas Aufwand treiben, damit es funktioniert. Das liegt daran, dass Browser
von Hause aus mit (RGB)-JPEGs umgehen können. Anders sieht es zum Beispiel mit einem PDF (pdf.php
) aus. Da reicht im
Normalfall schon dieser Code aus.
<?php
$pdf = file_get_contents('test.pdf');
$size = filesize('test.pdf');
header('Content-Disposition: attachment; filename=test.pdf');
header('Content-Length: '.$size);
echo $pdf;
?>
Klickt mal in der download.htm
auf den entsprechenden Link.
5. Ein Tipp
Spielt mal mit den Headern und diversen Browsern mit unterschiedlichen Einstellungen herum. Dann werdet ihr auch sehr schnell lernen, dass jeder Browser anders reagiert. Arbeitet auch ruhig mal mit anderen Dateitypen und den entsprechenden Headern. Schaden kann es auf keinen Fall.
zurück zum vorherigen Abschnitt weiter zum nächsten Abschnitt