Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from http import HTTPStatus
- from io import BytesIO
- from typing import Dict, Optional
- import boto3
- from botocore.client import BaseClient
- from botocore.exceptions import ClientError
- from app import config
- from app.common import common_api
- from app.common.utils import Base64File, InMemoryFile
- class AwsS3Processor:
- """A class that provides all the work with AWS S3"""
- def __init__(self, boto_client: BaseClient, bucket_name: str):
- self._client = boto_client
- self.bucket_name = bucket_name
- @classmethod
- def create_from_credentials(
- cls, aws_access_key_id: str, aws_secret_access_key: str, bucket_name: str
- ) -> "AwsS3Processor":
- client = boto3.client(
- "s3",
- aws_access_key_id=aws_access_key_id,
- aws_secret_access_key=aws_secret_access_key,
- )
- return cls(boto_client=client, bucket_name=bucket_name)
- @staticmethod
- def _generate_acl(is_private: bool) -> Dict:
- if is_private:
- return {"ACL": "private"}
- return {"ACL": "public-read"}
- def upload_in_memory_file(
- self, file: InMemoryFile, upload_to: str, is_private=False
- ):
- upload_to_key = f"{upload_to}/{file.full_filename}"
- try:
- extra_args = self._generate_acl(is_private=is_private)
- if file.content_type is not None:
- extra_args["ContentType"] = file.content_type
- self._client.upload_fileobj(
- Fileobj=file.file,
- Bucket=self.bucket_name,
- ExtraArgs=extra_args,
- Key=upload_to_key,
- )
- except Exception as e:
- raise ValueError("An error occurred while uploading: ", e)
- return upload_to_key
- def download_in_memory_file(self, key: str) -> Optional[BytesIO]:
- try:
- response = self._client.get_object(Bucket=self.bucket_name, Key=key)
- return BytesIO(response['Body'].read())
- except Exception as e:
- print(f"[ERROR] During downloading the file {key}. Error: ", e)
- return None
- @staticmethod
- def generate_url_to_file(file_name: str, bucket_name: str = "", is_private: bool = True):
- s3_client = boto3.client('s3')
- if is_private:
- try:
- response = s3_client.generate_presigned_url(
- "get_object", Params={"Bucket": bucket_name, "Key": file_name}, ExpiresIn=3600
- )
- except ClientError as e:
- print(str(e))
- return None
- return response
- return f"https://{bucket_name}.s3.amazonaws.com/{file_name}" if file_name else ""
- def generate_url_to_cloudfront(self, file_name: str, bucket_name: str = ""):
- raise NotImplemented
- def get_aws_s3_processor() -> AwsS3Processor:
- return AwsS3Processor.create_from_credentials(
- aws_access_key_id=config.AWS_ACCESS_KEY,
- aws_secret_access_key=config.AWS_ACCOUNT_SECRET_KEY,
- bucket_name=config.AWS_IMAGES_S3_BUCKET,
- )
- def upload_file_by_credentials_from_config(
- base64_image: str, upload_to: str, is_image: bool = False, is_private=True, filename_prefix: str = None
- ) -> str:
- filename = Base64File.generate_file_name()
- if filename_prefix is not None:
- filename = f"{filename_prefix}{filename}"
- try:
- file = Base64File.create_from_b64_string(b64string=base64_image, filename=filename)
- except ValueError:
- raise common_api.abort(message="Can not detect the mime type", code=HTTPStatus.BAD_REQUEST)
- allowed_extensions = config.ALLOWED_IMAGE_EXTENSIONS if is_image else config.ALLOWED_FILE_EXTENSIONS
- if not file.validate_file_extension(list_of_allowed_extensions=allowed_extensions):
- raise common_api.abort(
- message=f"Invalid file extension. Supported file types: {', '.join(allowed_extensions)}",
- code=HTTPStatus.BAD_REQUEST,
- )
- # Upload image to the s3 bucket
- s3_processor = get_aws_s3_processor()
- uploaded_to_path = s3_processor.upload_in_memory_file(
- file=file, upload_to=upload_to, is_private=is_private
- )
- return uploaded_to_path
- def download_file_by_credentials_from_config(key: str) -> Optional[BytesIO]:
- # download image from the s3 bucket
- return get_aws_s3_processor().download_in_memory_file(key)
Add Comment
Please, Sign In to add comment