Dateien vom Webserver mit X-Sendfile schneller ausliefern

Webserver sind für das ausliefern von statischen Dateien optimiert, bieten aber an sich keine große Möglichkeit zur Interaktion zwischen Nutzer und Server. Das brauchen sie auch nicht, da interaktive Webseiten über Skriptsprachen wie PHP, Python, Perl und weitere realisiert werden. Die durch ein Skript gesteuerte Auslieferung von statischen Dateien kann einige Vorteile haben, jedoch unterliegt dies auch den Beschränkungen der aktuellen Laufzeitumgebung. Um diese zu Umgehen kommt X-Sendfile ins Spiel.

Allgemein

X-Sendfile wird von vielen modernen Webservern wie Apache und lighttpd unterstützt. Dabei teilt ein aufgerufenes Skript dem Webserver mit dem X-Sendfile Header mit, welche Datei ausgeliefert werden soll und dieser kümmert sich um den Rest. Das hat den Vorteil, dass zum Beispiel eventuelle Speicherbeschränkungen der Skriptsprachen umgangen wird und das ein Download ohne weitere Vorkehrungen vom Endnutzer unterbrochen und fortgesetzt werden kann.

Konfiguration

Um X-Sendfile mit einem Apache Webserver zu nutzen muss mod_xsendfile installiert und aktiviert sein. Zum Beispiel muss dafür unter Ubuntu das Paket libapache2-mod-xsendfile installiert werden. Anschließend kann es mit folgendem Aufruf aktiviert werden.

$ sudo a2enmod xsendfile

Anschließend kann die Unterstützung von X-Sendfile noch gezielt aktiviert bzw. deaktiviert werden.

XSendFile On
XSendFileAllowAbove On

Dabei schaltet die Angabe von XSendFile die Unterstützung an bzw. aus. Es ist jedoch zu beachten, dass nur Dateien ausgeliefert werden, die in der Ordner-Hierarchie unter dem ausgeführten Skript liegen. Dieses Verhalten kann mit XSendFileAllowAbove so geändert werden, dass auch darüber liegende Dateien ausgeliefert werden.

Beispiel in PHP

Im folgenden Beispiel wird eine Möglichkeit gezeigt, wie eine Datei ohne X-Sendfile ausgeliefert werden kann.

$file = "meine.datei";

header('Content-type: ' . mime_content_type($file));
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Content-Length: '. filesize($file));
ob_clean();
flush();
$fp = fopen($file, 'r');
while(($content = fread($fp, 4096)) != '') {
 sleep(1);
 print $content;
}
fclose($fp);

Anschließend zum Vergleich das Beispiel mit der X-Sendfile Methode.

$file = "meine.datei";

header('Content-type: ' . mime_content_type($file));
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header("X-Sendfile: " . $file);

Sicherheit

Wichtig ist, dass die Namen der Dateien, die ausgeliefert werden sollen, sorgfältig überprüft werden. Wird dies nicht gemacht kann es Möglich sein, dass Außenstehende Einblick auf ansonsten geschützte Dateien erhalten. Dies gilt jedoch für X-Sendfile sowie die durch reines PHP realisierte Variante.

Verwandte Artikel