51 lines
2 KiB
Python
51 lines
2 KiB
Python
import uuid
|
|
from datetime import timedelta
|
|
|
|
from django.conf import settings
|
|
from drf_spectacular.utils import extend_schema
|
|
from rest_framework import status
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from apps.core.serializers import MediaPresignInputSerializer, MediaPresignOutputSerializer
|
|
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
|
|
from utils.clients.minio_client import minio_client
|
|
from utils.exceptions import ServiceUnavailable
|
|
|
|
|
|
class MediaPresignView(APIView):
|
|
"""Presigned MinIO upload URL for product/store images (icon, logo, cover, ...).
|
|
|
|
The client uploads the file bytes directly to MinIO with the returned
|
|
upload_url, then submits the returned object_key as the field value when
|
|
creating/updating the owning resource (e.g. Store.logo, Product.image).
|
|
"""
|
|
|
|
schema_tags = ['Media']
|
|
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
|
required_alternate_scopes = {
|
|
"POST": [[]],
|
|
}
|
|
|
|
@extend_schema(request=MediaPresignInputSerializer, responses={201: MediaPresignOutputSerializer})
|
|
def post(self, request):
|
|
serializer = MediaPresignInputSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
filename = serializer.validated_data['filename']
|
|
extension = filename.rsplit('.', 1)[-1] if '.' in filename else 'bin'
|
|
object_key = f'uploads/{uuid.uuid4()}.{extension}'
|
|
|
|
try:
|
|
upload_url = minio_client.presigned_put_object(
|
|
settings.MINIO_BUCKET_NAME,
|
|
object_key,
|
|
expires=timedelta(minutes=30),
|
|
)
|
|
except Exception:
|
|
raise ServiceUnavailable('خطا در دریافت لینک آپلود. لطفاً دوباره تلاش کنید.')
|
|
|
|
return Response(
|
|
MediaPresignOutputSerializer({'upload_url': upload_url, 'object_key': object_key}).data,
|
|
status=status.HTTP_201_CREATED,
|
|
)
|