123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- from django.shortcuts import render
- # Create your views here.
- import time
- from rest_framework import permissions, status, authentication
- from rest_framework.response import Response
- from rest_framework.views import APIView
- from .config_aws import (
- AWS_UPLOAD_BUCKET,
- AWS_UPLOAD_REGION,
- AWS_UPLOAD_ACCESS_KEY_ID,
- AWS_UPLOAD_SECRET_KEY
- )
- from .models import FileItem
- class FilePolicyAPI(APIView):
- """
- This view is to get the AWS Upload Policy for our s3 bucket.
- What we do here is first create a FileItem object instance in our
- Django backend. This is to include the FileItem instance in the path
- we will use within our bucket as you'll see below.
- """
- permission_classes = [permissions.IsAuthenticated]
- authentication_classes = [authentication.SessionAuthentication]
- def post(self, request, *args, **kwargs):
- """
- The initial post request includes the filename
- and auth credientails. In our case, we'll use
- Session Authentication but any auth should work.
- """
- filename_req = request.data.get('filename')
- if not filename_req:
- return Response({"message": "A filename is required"}, status=status.HTTP_400_BAD_REQUEST)
- policy_expires = int(time.time()+5000)
- user = request.user
- username_str = str(request.user.username)
- """
- Below we create the Django object. We'll use this
- in our upload path to AWS.
- Example:
- To-be-uploaded file's name: Some Random File.mp4
- Eventual Path on S3: <bucket>/username/2312/2312.mp4
- """
- file_obj = FileItem.objects.create(user=user, name=filename_req)
- file_obj_id = file_obj.id
- upload_start_path = "{username}/{file_obj_id}/".format(
- username = username_str,
- file_obj_id=file_obj_id
- )
- _, file_extension = os.path.splitext(filename_req)
- filename_final = "{file_obj_id}{file_extension}".format(
- file_obj_id= file_obj_id,
- file_extension=file_extension
- )
- """
- Eventual file_upload_path includes the renamed file to the
- Django-stored FileItem instance ID. Renaming the file is
- done to prevent issues with user generated formatted names.
- """
- final_upload_path = "{upload_start_path}{filename_final}".format(
- upload_start_path=upload_start_path,
- filename_final=filename_final,
- )
- if filename_req and file_extension:
- """
- Save the eventual path to the Django-stored FileItem instance
- """
- file_obj.path = final_upload_path
- file_obj.save()
- policy_document_context = {
- "expire": policy_expires,
- "bucket_name": AWS_UPLOAD_BUCKET,
- "key_name": "",
- "acl_name": "private",
- "content_name": "",
- "content_length": 524288000,
- "upload_start_path": upload_start_path,
- }
- policy_document = """
- {"expiration": "2019-01-01T00:00:00Z",
- "conditions": [
- {"bucket": "%(bucket_name)s"},
- ["starts-with", "$key", "%(upload_start_path)s"],
- {"acl": "%(acl_name)s"},
-
- ["starts-with", "$Content-Type", "%(content_name)s"],
- ["starts-with", "$filename", ""],
- ["content-length-range", 0, %(content_length)d]
- ]
- }
- """ % policy_document_context
- aws_secret = str.encode(AWS_UPLOAD_SECRET_KEY)
- policy_document_str_encoded = str.encode(policy_document.replace(" ", ""))
- url = 'https://{bucket}.s3-{region}.amazonaws.com/'.format(
- bucket=AWS_UPLOAD_BUCKET,
- region=AWS_UPLOAD_REGION
- )
- policy = base64.b64encode(policy_document_str_encoded)
- signature = base64.b64encode(hmac.new(aws_secret, policy, hashlib.sha1).digest())
- data = {
- "policy": policy,
- "signature": signature,
- "key": AWS_UPLOAD_ACCESS_KEY_ID,
- "file_bucket_path": upload_start_path,
- "file_id": file_obj_id,
- "filename": filename_final,
- "url": url,
- "username": username_str,
- }
- return Response(data, status=status.HTTP_200_OK)
|