Evita errores – Cómo almacenar imágenes en AWS S3 desde Flask - Episodio 23

Hoy vengo con evita errores a cómo almacenar imágenes en AWS S3 desde flask
🚀 Pasando de almacenamiento local a AWS S3. 📅 Diario de un SaaS
Uno de los desafíos en mi SaaS era la gestión de imágenes.
Inicialmente, las almacenaba en el servidor, pero esto presentaba varios problemas:
🔴 Espacio limitado en el VPS. Con el tiempo, subir muchas imágenes llenaría el almacenamiento.
🔴 Falta de escalabilidad. Si el SaaS crecía, gestionar archivos en el servidor sería un cuello de botella.
🔴 Tiempo de carga lento. No tener un CDN o almacenamiento optimizado afectaba la velocidad de carga.
La solución: migrar la gestión de imágenes a AWS S3.
Ya que esto me iba a permitir no incurrir en tener que aumentar espacio en el VPS así como también seguir con un modelo SaaS escalable.
Por eso, en este post te cuento cómo lo hice, los errores que encontré y cómo optimicé la integración. 🚀
🔍 Problema: Almacenamiento local no escalable
Hasta ahora, las imágenes se guardaban directamente en el VPS dentro de una carpeta /uploads/.
Y claro, esto tenía varias desventajas:
🔴 Riesgo de perder archivos. Si el servidor fallaba, las imágenes podían desaparecer.
🔴 Carga en el servidor. Cuantas más imágenes, más recursos consumía el VPS.
🔴 No era accesible globalmente. Para servir imágenes en diferentes regiones, necesitaba un almacenamiento distribuido.
Así que me puse a investigar y di con la solución de AWS S3.
Es decir, AWS S3 solucionaba todo esto al permitir un almacenamiento seguro, escalable y accesible globalmente. 🔥
¿Qué más podía pedir?
Una vez había encontrado la solución ya solo me quedaba implementarla...
🛠️ Configuración de AWS S3 e integración con Flask
Para migrar a S3, realicé los siguientes pasos:
✅ 1. Crear un bucket en AWS S3
1️⃣ Entré en la consola de AWS y fui a S3.
2️⃣ Creé un nuevo bucket con un nombre único (ejemplo: mi-saas-imagenes).
3️⃣ Configuré los permisos del bucket para que los archivos sean accesibles públicamente a través de una URL.
4️⃣ Activé la opción de versión de archivos para evitar sobrescribir imágenes por error.
✅ 2. Configurar credenciales de AWS en Flask
Para que Flask pudiera subir imágenes a S3, necesitaba autenticarme con AWS.
Así que en lugar de poner las credenciales en el código (¡nunca hagas esto!), usé variables de entorno:
1️⃣ Instalar boto3, el SDK de AWS para Python:
pip install boto3
2️⃣ Crear un archivo .env y agregar las credenciales de AWS:
AWS_ACCESS_KEY_ID=TU_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=TU_SECRET_KEY
AWS_REGION=us-east-1
AWS_S3_BUCKET=mi-saas-imagenes
3️⃣ Cargar las variables en Flask con python-dotenv:
pip install python-dotenv
Luego, en app.py:
from dotenv import load_dotenv
import os
load_dotenv()
AWS_ACCESS_KEY = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_REGION = os.getenv('AWS_REGION')
AWS_S3_BUCKET = os.getenv('AWS_S3_BUCKET')
✅ 3. Crear un endpoint /upload-image para subir imágenes
Con Flask y boto3, creé un endpoint para manejar la subida de imágenes a AWS S3:
import boto3
from flask import Flask, request, jsonify
app = Flask(__name__)
s3 = boto3.client('s3', aws_access_key_id=AWS_ACCESS_KEY, aws_secret_access_key=AWS_SECRET_KEY, region_name=AWS_REGION)
@app.route('/upload-image', methods=['POST'])
def upload_image():
if 'file' not in request.files:
return jsonify({'error': 'No se encontró el archivo'}), 400
file = request.files['file']
file_name = file.filename
s3.upload_fileobj(file, AWS_S3_BUCKET, file_name, ExtraArgs={'ACL': 'public-read'})
file_url = f"https://{AWS_S3_BUCKET}.s3.{AWS_REGION}.amazonaws.com/{file_name}"
return jsonify({'url': file_url})
🔹 ¿Qué hace este código?
✅ Recibe una imagen desde un formulario o API.
✅ La sube a AWS S3 con permisos públicos.
✅ Devuelve la URL de la imagen alojada en S3.
Ahora cualquier usuario puede subir imágenes y recibir una URL accesible globalmente. 🚀
❌ Errores encontrados y cómo los solucioné
🔴 AccessDenied: La imagen no es accesible públicamente
Solución:
- Asegurar que el archivo se sube con
ACL: public-readenExtraArgs. - Revisar la configuración del bucket para permitir accesos públicos.
🔴 botocore.exceptions.NoCredentialsError: No se encontraron credenciales
Solución:
- Verificar que las credenciales están cargadas correctamente desde
.env. - Ejecutar
echo $AWS_ACCESS_KEY_IDen la terminal para comprobar si las variables de entorno están disponibles.
🔴 RequestEntityTooLarge: El archivo es demasiado grande
Solución:
- Configurar un límite de tamaño de archivo en la API de Flask.
- Habilitar multipart upload en boto3 para archivos pesados.

💡 Aprendizajes del proceso
🔹 Guardar imágenes en el servidor es una mala idea
Al principio parecía fácil, pero se vuelve insostenible a medida que crece la aplicación.
Básicamente es una mierda y a medida que vaya creciendo la mierda se hará más grande.
Es decir, más imágenes implica más espacio.
Y claro más espacio implica más coste en infraestructura.
Y no solo eso, también tiene una implicación directa en el rendimiento.
🔹 AWS S3 simplifica el manejo de archivos y mejora el rendimiento
Las imágenes ahora cargan más rápido y son accesibles desde cualquier parte del mundo.
🔹 Usar variables de entorno evita exponer credenciales
Nunca se deben escribir las credenciales en el código. .env y python-dotenv son imprescindibles.
🔹 Validar y optimizar imágenes antes de subirlas
Para evitar errores, es clave establecer límites de tamaño y formato en la API.
Conclusión y reflexiones
Mi principal obsesión es que haya una buena experiencia de usuario.
Y claro, esto implica que todo vaya fluido y si empiezan a subir imágenes la curva de rendimiento se iba a aplanar para acabar siendo decreciente.
¿ A ti te gustaría usar una herramienta que funciona lenta?
Por supuesto que no.
Y por eso es una de mis obsesiones.
Reflexión
Siento que ando haciendo camino y que hay tramos que estoy abriendo paso en una densa selva a machetazos y...
Otras veces, siento que ando por un desierto árido dónde no hay nada.
Y es un camino duro, muy duro, pero nada que pueda hacer mella en mi pasión e ilusión.
Así que seguiremos haciendo camino!
🚀 Próximos pasos
Con la gestión de imágenes optimizada, el siguiente paso es proteger credenciales y mejorar la seguridad con variables de entorno. 🔒🔥
➡️ ¿Cómo manejas las imágenes en tu SaaS?
¿Prefieres AWS S3 o tienes otra solución?
Cuéntamelo en los comentarios.
Si quieres conocer otros artículos parecidos a Evita errores – Cómo almacenar imágenes en AWS S3 desde Flask - Episodio 23 puedes visitar la categoría Proyecto-IA.

Deja una respuesta