readfile()
Die PHP-Funktion readfile() liest eine Datei und gibt deren Inhalt direkt an den Browser aus – ideal für Datei-Downloads.
Einführung
Die PHP-Funktion readfile() liest eine Datei und schreibt sie direkt in den Ausgabepuffer, wobei sie die Anzahl der gelesenen Bytes zurückgibt. Da die Datei direkt zur Ausgabe gestreamt wird, anstatt sie vollständig in einer PHP-Variable zu halten, ist dies der speichereffizienteste Weg, eine Datei an den Browser zu senden – genau deshalb ist sie das Standardwerkzeug für Datei-Downloads.
Dieses Kapitel behandelt die Syntax und Parameter von readfile(), den Rückgabewert, den Unterschied zu verwandten Funktionen wie file_get_contents() und fread() sowie die sichere Verwendung zum Anzeigen und Herunterladen von Dateien.
Syntax
readfile(
string $filename,
bool $use_include_path = false,
?resource $context = null
): int|false| Parameter | Beschreibung |
|---|---|
$filename | Pfad (oder URL, wenn allow_url_fopen aktiviert ist) der zu lesenden und auszugebenden Datei. |
$use_include_path | Wenn true, durchsucht PHP auch den include_path nach der Datei. Standardmäßig false. |
$context | Eine optionale Stream-Kontext-Ressource (erstellt mit stream_context_create()). |
Rückgabewert: die Anzahl der gelesenen Bytes oder false bei einem Fehler. Der Rückgabewert sollte immer überprüft und nicht ignoriert werden, da eine fehlende Datei eine Warnung ausgibt und trotzdem eine unvollständige (oft leere) Antwort sendet.
Wie readfile() funktioniert
Wenn readfile() aufgerufen wird, öffnet PHP die Datei, kopiert ihre Bytes in Blöcken in den Ausgabepuffer und sendet sie an den Client. Der gesamte Inhalt wird nie in einen PHP-String geladen, sodass der Speicherverbrauch auch bei mehrere Gigabyte großen Dateien gering bleibt. Der Nachteil: Es gibt keine Möglichkeit, die Daten zu transformieren – die Ausgabe ist eine bytegetreue Kopie der Datei.
readfile() vs. die Alternativen
Die Wahl der richtigen Funktion ist wichtig:
readfile()— Datei direkt zur Ausgabe streamen. Am besten für Downloads und das Ausliefern roher Dateien geeignet. Kein Rückgabe-String, nur die Anzahl gesendeter Bytes.file_get_contents()— Die gesamte Datei in einen String einlesen, um sie zu ändern, zu durchsuchen oder zu speichern. Verbraucht Speicher proportional zur Dateigröße.fopen()+fread()— Ein Handle für feingranuliertes, positionsbasiertes Lesen öffnen; verwenden, wenn in kontrollierten Blöcken gelesen oder gesucht werden muss.highlight_file()— Eine Datei mit PHP-Syntaxhervorhebung ausgeben (zum Anzeigen von Quellcode).
Faustregel: Wenn eine Datei nur gesendet werden soll, readfile() verwenden; wenn die Datei verarbeitet werden soll, stattdessen in eine Variable einlesen.
Beispiele
Beispiel 1: Eine Textdatei anzeigen
<?php
readfile('example.txt');Dies sendet den Inhalt von example.txt direkt an den Browser. Ohne gesetzten Content-Type-Header gilt der Standardwert des Servers (normalerweise text/html).
Beispiel 2: Den Rückgabewert prüfen
readfile() gibt die Byte-Anzahl zurück, was für die Protokollierung oder Fehlerbehandlung nützlich ist:
<?php
$bytes = readfile('example.txt');
if ($bytes === false) {
http_response_code(404);
echo 'File not found.';
}Beispiel 3: Einen Download erzwingen
Damit der Browser eine Datei herunterlädt, anstatt sie anzuzeigen, müssen die richtigen Header vor jeder Ausgabe gesendet und dann readfile() aufgerufen werden:
<?php
$file = 'report.pdf';
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;Content-Type: application/octet-streamteilt dem Browser mit, dass es sich um einen binären Download handelt.Content-Disposition: attachment; filename="..."löst den „Speichern unter"-Dialog aus und legt den vorgeschlagenen Dateinamen fest.Content-Lengthermöglicht dem Browser, einen genauen Fortschrittsbalken anzuzeigen.
Die Header stammen von der Funktion header() und müssen gesendet werden, bevor die Funktion Bytes ausgibt – andernfalls tritt ein „headers already sent"-Fehler auf.
Häufige Fallstricke
- Niemals nicht bereinigten Benutzereingaben als
$filenameübergeben. Ein Wert wie../../etc/passwdwürde einem Angreifer ermöglichen, beliebige Dateien zu lesen (Path-Traversal-Angriff). Erlaubte Dateien auf eine Whitelist setzen oder den Pfad durchbasename()laufen lassen und auf ein bekanntes Verzeichnis beschränken. - Keine Ausgabe vor den Headern. Selbst ein versehentliches Leerzeichen oder BOM vor
<?phpgilt als Ausgabe und brichtContent-Disposition. - Ausgabepufferung bei großen Dateien leeren. Wenn die Ausgabepufferung aktiviert ist, kann die Datei immer noch im Speicher gepuffert werden. Vor
readfile()ob_end_clean()(oderflush()) aufrufen, wenn sehr große Dateien gestreamt werden. - Remote-URLs lesen erfordert, dass
allow_url_fopeninphp.iniaktiviert ist.
Fazit
readfile() ist PHPs bevorzugte Funktion, um eine Datei mit minimalem Speicheraufwand an den Client zu senden: Sie streamt Bytes direkt zur Ausgabe und gibt die Anzahl der gesendeten Bytes zurück. Für Downloads und das Ausliefern roher Dateien verwenden, mit header() für Downloads kombinieren, den Dateinamen validieren, um Path-Traversal-Angriffe zu vermeiden, und stattdessen file_get_contents() verwenden, wenn der Dateiinhalt tatsächlich in einer Variable benötigt wird.