1. Crear el Bucket
En AWS:
Ejemplo
Nombre:
mi-empresa-archivos
Region: # Elegir acorde con la region de tu servidor de backend
us-east-1
Lo importante es:
Dejar todo activado.
Eso hace que absolutamente nadie pueda acceder mediante
https://bucket.s3.amazonaws.com/archivo.pdf
aunque conozca el nombre.
Politicas de bucket AWS S3
2. IAM
Nunca se usan las credenciales de la cuenta root.
Se crea un usuario IAM.
IAM
Create User
django-production
Después una política.
Ejemplo:
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":[
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource":"arn:aws:s3:::mi-empresa-archivos/*"
},
{
"Effect":"Allow",
"Action":[
"s3:ListBucket"
],
"Resource":"arn:aws:s3:::mi-empresa-archivos"
}
]
}
Después se generan
Access Key
3. Variables de entorno
Normalmente se guardan en tu settings.py o un archivo como .env o settings_server.py
AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
AWS_STORAGE_BUCKET_NAME=mi-empresa-archivos
AWS_S3_REGION_NAME=us-east-1
AWS_S3_SIGNATURE_VERSION=s3v4
AWS_QUERYSTRING_EXPIRE=300
donde
4. Instalar librerías
o
pip install django-storages boto3
4. Instalar librerías
o
pip install django-storages boto3
5. settings.py
Agregar
INSTALLED_APPS += [
"storages",
]
Después
AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME")
AWS_S3_REGION_NAME = os.getenv("AWS_S3_REGION_NAME")
AWS_S3_SIGNATURE_VERSION = "s3v4"
AWS_QUERYSTRING_AUTH = True
AWS_QUERYSTRING_EXPIRE = 300
AWS_DEFAULT_ACL = None
Muy importante:
Desde hace varios años Amazon recomienda no usar ACLs.
Storage
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
Con eso todos los
guardarán archivos en S3.
6. Modelo
class Documento(models.Model):
nombre = models.CharField(max_length=100)
archivo = models.FileField(
upload_to="documentos/"
)
Cuando haces
el archivo ya no queda en
sino en
por ejemplo
7. Subir archivos
Ejemplo
documento = Documento()
documento.archivo.save(
"contrato.pdf",
ContentFile(pdf)
)
Internamente django-storages hace
contra S3.
8. Obtener URL
Como el bucket es privado,
no devuelve
https://bucket.s3.amazonaws.com/archivo.pdf
sino algo parecido a
https://mi-empresa-archivos.s3.amazonaws.com/documentos/contrato.pdf
?X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=...
&X-Amz-Date=...
&X-Amz-Expires=300
&X-Amz-Signature=...
Es una URL firmada.
Después de 5 minutos
9. Generar URL manualmente con boto3
Muchas empresas prefieren hacerlo manualmente.
import boto3
client = boto3.client(
"s3",
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
region_name=settings.AWS_S3_REGION_NAME
)
url = client.generate_presigned_url(
ClientMethod="get_object",
Params={
"Bucket": settings.AWS_STORAGE_BUCKET_NAME,
"Key": "documentos/factura.pdf"
},
ExpiresIn=300
)
Obtienes exactamente la misma URL temporal.
10. Subida directa desde Django
Flujo
Usuario
↓
POST /upload/
↓
Django
↓
S3 PutObject
↓
Guardar ruta en BD
archivo = request.FILES["archivo"]
modelo.archivo = archivo
modelo.save()
No necesitas escribir código de boto3 porque django-storages se encarga del proceso.
11. Variables importantes
| Variable |
Función |
| AWS_ACCESS_KEY_ID |
Llave pública del usuario IAM. |
| AWS_SECRET_ACCESS_KEY |
Llave secreta asociada. |
| AWS_STORAGE_BUCKET_NAME |
Nombre del bucket donde se almacenan los archivos. |
| AWS_S3_REGION_NAME |
Región del bucket (por ejemplo, us-east-1). |
| AWS_S3_SIGNATURE_VERSION |
Versión de firma usada para las URLs (s3v4 es la recomendada). |
| AWS_QUERYSTRING_AUTH |
Si es True, genera URLs firmadas para acceso privado. |
| AWS_QUERYSTRING_EXPIRE |
Tiempo de vida de la URL firmada en segundos. |
| AWS_DEFAULT_ACL |
Debe ser None para seguir las recomendaciones actuales de AWS. |
| DEFAULT_FILE_STORAGE |
Indica a Django que use S3 como backend de almacenamiento. |