HOWTO · Flask

Herunterladen einer Datei mit Flask

Mit dieser Erklärung lernen wir, wie man mit Hilfe der send_file-Funktion in Flask einen herunterladbaren Link zum Herunterladen einer Datei als Anhang erstellt.

Auf dieser Seite

Damit ein Link in Flask eine Datei herunterlädt, definieren Sie eine Route, die send_file(path, as_attachment=True) zurückgibt, und verweisen Sie im Template mit url_for auf diese Route. Die Datei muss unter dem von der Route verwendeten Pfad vorhanden sein.

Eine Datei über eine Flask-Downloadroute zurückgeben

send_file erstellt die Antwort, die die Datei enthält. Die View muss diese Antwort zurückgeben: Wird send_file ohne return aufgerufen, erhält Flask nicht die vorgesehene Antwort. Mit as_attachment=True sendet Flask die Datei als Anhang. Der Browser bietet sie dann zum Herunterladen an, statt sie als Seite anzuzeigen.

Von einem Template aus auf die Downloadroute verlinken

Verwenden Sie url_for mit dem Endpunktnamen der Route. Standardmäßig verwendet Flask den Namen der View-Funktion als Endpunkt. Deshalb heißen der Link und die unten gezeigte Funktion beide download_file. URL-Pfad (/download) und Endpunktname sind zwei verschiedene Dinge: Beim Rendern des Templates sucht url_for den Endpunkt. Ein GET-Link behebt keinen falsch geschriebenen oder nicht registrierten Endpunkt.

Das Template gehört in einen Ordner namens templates neben app.py:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

<h2>Download the sample file</h2>
<p><a href="{{ url_for('download_file') }}">Download</a></p>

Einen verlässlichen Dateipfad und die Anhangseinstellung verwenden

Bauen Sie den Pfad aus app.root_path auf. So ist er an das Anwendungsverzeichnis gebunden und hängt nicht vom aktuellen Arbeitsverzeichnis der Shell ab. Dieses lokale Beispiel erstellt eine kleine Textdatei neben app.py; ersetzen Sie den Pfad durch den Speicherort der Datei, die Sie bereitstellen möchten. Übernehmen Sie keinen beliebigen Dateisystempfad aus einer URL oder einem Formular und geben Sie ihn direkt an send_file weiter.

Standardmäßig wird der Dateiname aus dem Pfad übernommen. In diesem Beispiel wird die Datei daher als sample.txt angeboten. Soll der gespeicherte Name vom Namen des Downloads abweichen, geben Sie send_file gezielt einen Wert für download_name mit. Behalten Sie die Kontrolle über den gewählten Pfad und prüfen Sie vor dem Bereitstellen, ob die Datei verfügbar ist. Ein Pfad aus vertrauenswürdigen Anwendungseinstellungen lässt sich leichter beurteilen als ein von Besuchern angegebener Pfad.

Speichern Sie den folgenden Code als app.py. Er legt das Template und die Beispieldatei neben der Anwendung an und verwendet anschließend den Flask-Testclient für eine Anfrage, ohne einen Serverprozess zu starten:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

from pathlib import Path

from flask import Flask, render_template, send_file

app = Flask(__name__)
template_dir = Path(app.root_path) / "templates"
template_dir.mkdir(exist_ok=True)
(template_dir / "index.html").write_text(
    '<p><a href="{{ url_for(\'download_file\') }}">Download</a></p>',
    encoding="utf-8",
)
SAMPLE_FILE = Path(app.root_path) / "sample.txt"
SAMPLE_FILE.write_text("A file served by Flask.\n", encoding="utf-8")


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/download")
def download_file():
    return send_file(SAMPLE_FILE, as_attachment=True)


if __name__ == "__main__":
    with app.test_client() as client:
        print(client.get("/").get_data(as_text=True).strip())
        response = client.get("/download")
        print(response.status_code)
        print(response.headers["Content-Disposition"])
        print(response.get_data(as_text=True), end="")

Das Template löst download_file zu /download auf, und der Testclient fordert diese Route an. Bei der Ausführung des Skripts werden der gerenderte Link, der Antwortstatus, der Anhang-Header und der Dateiinhalt ausgegeben. Der Anhang-Header zeigt, dass der Browser die Antwort herunterladen soll; anhand des Antwortinhalts lässt sich prüfen, ob die ausgewählte Datei bereitgestellt wurde.

Das vollständige Beispiel ausführen und überprüfen

Installieren Sie Flask in Ihrer Projektumgebung, falls es dort noch nicht vorhanden ist, und führen Sie dann python app.py aus, um den gerenderten Link und die Downloadantwort lokal zu prüfen. Um dieselben Routen im Browser auszuprobieren, starten Sie den Flask-Entwicklungsserver mit flask --app app run, öffnen Sie http://127.0.0.1:5000/ und wählen Sie Download. Der Browser sollte sample.txt herunterladen; beim direkten Aufruf von /download wird derselbe Anhang bereitgestellt. Beenden Sie den Server mit Strg+C. Der Debugmodus ist nur für die lokale Entwicklung gedacht. Aktivieren Sie den interaktiven Debugger nicht auf einem öffentlich erreichbaren Server.