Hi Martin,
Denn während [readfile()] erst den gesamten Dateiinhalt in den Arbeitsspeicher lädt [...], wird bei readfile() dieser Dateiinhalt einfach nur durchgereicht, ohne ihn zwischenzuspeichern.
Ich hatte in der Tat auch erst readfile() da stehen ;-) Hab es dann aber zu echo file_get_contents() umgeändert, da im PHP Manual steht:
file_get_contents() is the preferred way to read the contents of a file
into a string. It will use memory mapping techniques if supported by your
OS to enhance performance.
Das hört sich ja erst mal recht vernünftig an. Um den Inhalt durchzuschleusen dürfte readfile() eigentlich besser sein, allerdings nur, wenn es PHP-intern auch gescheit programmiert ist - und da hab ich etwas Bedenken ;-) Wie sieht es mit Output-Buffering aus? Sorgt readfile() gezielt für flush() bzw. kann man readfile() dazu bringen dies zu tun? Wie groß sind die Blöcke, in denen readfile() einliest und ausgibt?
Im Zweifelsfall also lieber selber machen:
// Datei öffnen
$fp = fopen('path/to/file.ext', 'r');
// für Lesezugriff sperren
flock($fp, LOCK_SH);
// solange Ende nicht erreicht
while(!feof($fp)) {
// 100 kB einlesen und ausgeben
echo fread($fp, 102400);
// explizit an Client senden
flush();
}
// Datei schließen
fclose($fp);
Wäre jetzt nur noch die Frage, welche Größe als Buffer optimal ist... Ich denke 100 KB sind nicht schlecht, wenn 50 Leute gleichzeitig die Datei herunterladen sind knapp 5 MB Arbeitsspeicher belegt, was IHMO akzeptabel ist. Gleichzeitig muss der Server nicht so viele Schleifen durchlaufen, wie er es bei z.B. 10 KB Blöcken machen müsste.
Eventuell wären auch 500 KB als Buffer noch akzeptabel, dann wären bei 50 gleichzeitigen Downloads allerdings knapp 25 MB Arbeitsspeicher belegt. Muss man sich eben überlegen, wo man Prioritäten setzt ;-)
Viele Grüße,
~ Dennis.