Zur Übersicht

X-Sendfile

Thomas Schedler
Thomas Schedler Aktualisiert am 31. Juli 2024
x-sendfile

Wer kennt sie nicht, die Probleme beim Download grosser Dokumente, die nicht per statischer URL erreichbar sind?

Gründe, wieso Dokumente nicht direkt vom Webserver ausgeliefert werden bzw. sich sogar ausserhalb des öffentlichen Bereiches befinden, gibt es einige. Sei es zum Schutz vor unbefugtem Download oder einfach nur für die Statistik. Auf jeden Fall muss eine aktive Komponente dazwischen geschaltet werden.

In unserem Fall handelt es sich dabei um PHP.

Mit der Funktion readfile lässt sich das auch im Normalfall ohne Probleme bewerkstelligen.


Rein theoretisch liest PHP 8K chunks in den Speicher und flushed diese dann auch direkt an den Browser. Memory-Overflow, Timeouts oder ähnliches sollten daher eigentlich kein Problem darstellen. Und trotzdem kommt es, vor allem bei grösseren Dokumenten, immer wieder zu fehlerhaften Donwloads.

Bei meiner Recherche im Web bin ich dann auf ein vielversprechendes Apache-Module namens XSendFile gestossen.

XSendFile verarbeitet X-SENDFILE Headers, die z.B. per PHP gesetzt werden und liefert dann das gewünschte Dokument über die internen Funktionen des Apache Webserver aus. D.h. es ist kein Einlesen des Dokumentes per PHP in den Speicher nötig. Apache kümmert sich selbst um den Download mit sämtlichen Vorteilen wie z.B. optimale Auslieferung durch sendfile und mmap (falls vorhanden), korrekte Cache-Header wie Etag und If-Modified-Since, als ob die Datei statisch ausgeliefert wird.

isLoggedIn()) {

    $file = '/var/www/massiveart.com/secure/report.pdf';

    if (file_exists($file)) {
        header('X-Sendfile: ' . $file);   
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($file) . '"'); 

        exit;
    }
}

Das Module zu installieren ist eine Kleinigkeit und hat bei uns ein Problem gelöst, welches wir zunächst nicht nachvollziehen konnten.

Hier noch eine kurze Anleitung wie das Module für Ubuntu Server kompiliert und aktiviert werden kann:

wget https://tn123.org/mod_xsendfile/mod_xsendfile-0.12.tar.gz --no-check-certificate

// entpacken
tar -zxvf mod_xsendfile-0.12.tar.gz

cd mod_xsendfile-0.12

// kompilieren
apxs2 -cia mod_xsendfile.c

// Apache Module Load-File erstellen
echo "LoadModule xsendfile_module /usr/lib/apache2/modules/mod_xsendfile.so" >> /etc/apache2/mods-available/xsendfile.load

// Module aktivieren
a2enmod xsendfile

Jetzt muss die Erweiterung nur noch für den gewünschten VirtualHost aktiviert werden.


    ServerName www.massiveart.com
    DocumentRoot /var/www/massiveart.com/public
    
        XSendFile on
        XSendFilePath /var/www/massiveart.com/secure
    

Apache neu starten und schon läuft das Module.

Thomas Schedler
Thomas Schedler
Co-Founder & CEO Sulu
Thomas is Co-founder & CEO of Sulu GmbH, the company behind the open source content management platform Sulu. Before launching Sulu as a separate business, Thomas worked eight years as a Software Architect for MASSIVE ART WebServices. He was the technical lead for various digitalization projects, from complex business websites to e-commerce systems and IoT platforms. During this time the first version of Sulu, the open source CMS, was developed which has become the foundation of Sulu GmbH. In his spare time Thomas loves to cook and spend time in the mountains with his family.