HOWTO · Flask

Télécharger un fichier à l'aide de Flask

Nous allons apprendre, avec cette explication, comment faire un lien téléchargeable pour télécharger un fichier en pièce jointe à l'aide de la fonction send_file dans Flask.

Sur cette page

Pour qu’un lien télécharge un fichier avec Flask, définissez une route qui renvoie send_file(path, as_attachment=True), puis faites pointer vers cette route un lien du modèle généré avec url_for. Le fichier doit se trouver au chemin utilisé par la route.

Renvoyer un fichier depuis une route de téléchargement Flask

send_file crée la réponse qui transporte le fichier. La vue doit renvoyer cette réponse : appeler send_file sans return ne fournit pas à Flask la réponse attendue. Avec as_attachment=True, Flask transmet le fichier en pièce jointe afin que le navigateur propose de le télécharger au lieu de le traiter comme une page à afficher.

Créer un lien vers la route de téléchargement dans un modèle

Utilisez url_for avec le nom du point de terminaison de la route. Par défaut, Flask utilise le nom de la fonction de vue comme point de terminaison ; le lien et la fonction ci-dessous utilisent donc tous deux download_file. Le chemin d’URL (/download) et le nom du point de terminaison sont deux éléments distincts : url_for recherche le point de terminaison lors du rendu du modèle. Un lien GET ne corrige pas un point de terminaison mal orthographié ou non enregistré.

Le modèle doit se trouver dans un dossier nommé templates, à côté de app.py :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

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

Utiliser un chemin de fichier fiable et configurer la pièce jointe

Construisez le chemin à partir de app.root_path pour l’ancrer au répertoire de l’application, sans dépendre du répertoire de travail actuel du shell. Cet exemple local crée un petit fichier texte à côté de app.py ; remplacez ce chemin par celui du fichier que vous voulez transmettre. N’acceptez pas un chemin arbitraire fourni par une URL ou un formulaire pour le transmettre directement à send_file.

Par défaut, le nom de la pièce jointe est tiré du chemin : dans cet exemple, le fichier est donc proposé sous le nom sample.txt. Si le nom enregistré doit différer du nom du téléchargement, transmettez une valeur download_name explicite à send_file. Gardez la maîtrise du chemin choisi et vérifiez que le fichier est disponible avant de le transmettre ; un chemin construit à partir de paramètres fiables de l’application est plus facile à contrôler qu’un chemin fourni par un visiteur.

Enregistrez le code suivant sous app.py. Il crée le modèle et le fichier d’exemple à côté de l’application, puis utilise le client de test Flask pour envoyer une requête sans démarrer de processus serveur :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

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="")

Le modèle résout download_file en /download, et le client de test envoie une requête à cette route. Lorsque vous exécutez le script, il affiche le lien rendu, le statut de la réponse, l’en-tête de pièce jointe et le contenu du fichier. L’en-tête de pièce jointe permet de vérifier que le navigateur est invité à télécharger la réponse ; la vérification du corps confirme que le fichier choisi a été transmis.

Exécuter et vérifier l’exemple complet

Installez Flask dans l’environnement de votre projet si ce n’est pas déjà fait, puis exécutez python app.py pour vérifier localement le lien rendu et la réponse de téléchargement. Pour tester les mêmes routes dans un navigateur, démarrez le serveur de développement Flask avec flask --app app run, ouvrez http://127.0.0.1:5000/ et sélectionnez Download. Le navigateur devrait télécharger sample.txt ; accéder directement à /download transmet la même pièce jointe. Arrêtez le serveur avec Ctrl+C. Le mode débogage est réservé au développement local ; ne démarrez pas le débogueur interactif sur un serveur accessible publiquement.