Cómo servir ficheros y contenido estático con Flask

Servir contenido estático en Flask

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…

¿Quieres ser expert@ en Python? Recibe trucos Python y las últimas novedades del blog

¡Eyyy! Esto también te puede interesar 👇

* Te informo de que los datos de carácter personal que proporciones al comentar serán tratados por Juan José Lozano Gómez como responsable de esta web. La Finalidad es moderar los comentarios. La Legitimación es gracias a tu consentimiento. Destinatarios: tus datos se encuentran alojados en Disqus (disqus.com), mi sistema de comentarios, que está acogido al acuerdo de seguridad EU-US Privacy. Podrás ejercer Tus Derechos de Acceso, Rectificación, Limitación o Suprimir tus datos enviando un email a juanjo@j2logo.com. Encontrarás más información en la POLÍTICA DE PRIVACIDAD.

Sobre j2logo

j2logo profile

Quiero ayudarte a que seas mejor programador/a, pero no uno cualquiera, sino uno de los top.

¿Quieres ser expert@ en Python? 🐍

❤️ He ayudado a miles de programadores/as como tú a ser mejores Pythonistas

📩 Recibe de vez en cuando trucos y scripts Python y las últimas novedades del blog

* Al enviar el formulario confirmas que aceptas la POLITICA DE PRIVACIDAD

¿Quieres ser expert@ en PYTHON?

j2logo-pythonistas

❤️ He ayudado a miles de programadores/as como tú

📩 Recibe trucos, scripts y las novedades del blog

¿Quieres dominar Python?

Python, Guía para ser un Pythonista

El curso con el que aprender el lenguaje desde cero. Con mi soporte y ayuda.

OFERTA BLACK FRIDAY

35% de descuento