Flask, por defecto, está diseñado para devolver respuestas de tipo HTML. Sin embargo, hay ocasiones en que debemos devolver el contenido de un fichero. Por ejemplo, para hacer accesible el fichero robots.txt, el fichero del mapa del sitio (sitemap.xml) o las imágenes subidas por los usuarios. Este tutorial te muestra las distintas posibilidades que existen para servir ficheros y contenido estático en Flask.
Servir contenido estático en Flask con send_file
Tal y como te indicaba en la introducción, imagina que quieres servir con Flask el fichero robots.txt. Una de las posibilidades que existen es hacer uso de la función send_file()
. Veamos un ejemplo de su uso:
from flask import send_file @app.route('/robots.txt') def send_robots_txt(): return send_file(app.config['BASE_DIR'] + '/robots.txt')
🎯 El fichero robots.txt le indica a los bots y arañas que visitan tu web a qué partes del sitio pueden acceder y a cuáles no.
Como puedes apreciar, la función send_file()
devuelve el contenido de un fichero. Fíjate bien que a dicha función se le pasa como argumento la ruta completa del archivo a devolver.
Imagina ahora que tu aplicación utiliza un endpoint para devolver imágenes que los usuarios suben a tu web. El endpoint podría ser similar al siguiente:
import os from flask import send_file @app.route('/media/<path:filename>') def media_file(filename): file_path = os.path.join(app.config['MEDIA_DIR'], filename) return send_file(file_path)
❗️ IMPORTANTE: Nunca debes pasar un nombre de fichero a esta función que directamente provenga de un usuario. Esto supone un agujero de seguridad ya que se podrían consultar ficheros privados y restringidos de tu sitio.
Devolver ficheros con send_from_directory
Otro modo de devolver el contenido de un fichero en Flask es usar la función send_from_directory()
. send_from_directory()
utiliza la función send_file()
para servir contenido estático en Flask. La principal diferencia con send_file()
es que a send_from_directory()
se le pasan dos argumentos: un directorio y un nombre de fichero, de tal manera que busca si el fichero está en el directorio. En caso de que lo encuentre lo devuelve y si no lo hace devuelve un error.
Veamos el mismo ejemplo de la sección anterior pero usando esta función:
from flask import send_from_directory @app.route('/media/<path:filename>') def media_posts(filename): return send_from_directory(app.config['MEDIA_DIR'], filename)
La mejor forma de servir contenido estático en Flask
Arriba hemos visto dos formas de servir contenido estático de una aplicación desde Flask. Sin embargo, no es lo recomendable, dado que el framework no está preparado para ello (de hecho, casi ningún framework lo está).
Generalmente, el contenido estático de una aplicación debe ser servido por un servidor web como Nginx o Apache o, mejor aún, por un CDN. Los servidores webs sí son capaces de procesar peticiones y devolver el contenido de ficheros estáticos de manera muy eficiente. Deberías hacer uso de ellos, en la medida de lo posible, para servir este tipo de contenido pero, eso ya es otro tema…