storage.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. from contextlib import closing
  2. from typing import Union, Generator
  3. import boto3
  4. from botocore.exceptions import ClientError
  5. from app.exceptions.exception import ResourceNotFoundError
  6. from config.storage import settings as s3_settings
  7. class Storage:
  8. def __init__(self):
  9. self.bucket_name = None
  10. self.client = None
  11. def init(self):
  12. self.bucket_name = s3_settings.S3_BUCKET_NAME
  13. self.client = boto3.client(
  14. service_name="s3",
  15. aws_access_key_id=s3_settings.S3_ACCESS_KEY,
  16. aws_secret_access_key=s3_settings.S3_SECRET_KEY,
  17. # endpoint_url=s3_settings.S3_ENDPOINT,
  18. region_name=s3_settings.S3_REGION,
  19. )
  20. def save(self, filename, data):
  21. self.client.put_object(Bucket=self.bucket_name, Key=filename, Body=data)
  22. def save_from_path(self, filename, local_file_path):
  23. self.client.upload_file(
  24. Filename=local_file_path, Bucket=self.bucket_name, Key=filename
  25. )
  26. def load(self, filename: str, stream: bool = False) -> Union[bytes, Generator]:
  27. if stream:
  28. return self.load_stream(filename)
  29. else:
  30. return self.load_once(filename)
  31. def load_once(self, filename: str) -> bytes:
  32. try:
  33. with closing(self.client) as client:
  34. data = client.get_object(Bucket=self.bucket_name, Key=filename)[
  35. "Body"
  36. ].read()
  37. except ClientError as ex:
  38. if ex.response["Error"]["Code"] == "NoSuchKey":
  39. raise ResourceNotFoundError("File not found")
  40. else:
  41. raise
  42. return data
  43. def load_stream(self, filename: str) -> Generator:
  44. def generate(filename: str = filename) -> Generator:
  45. try:
  46. with closing(self.client) as client:
  47. response = client.get_object(Bucket=self.bucket_name, Key=filename)
  48. for chunk in response["Body"].iter_chunks():
  49. yield chunk
  50. except ClientError as ex:
  51. if ex.response["Error"]["Code"] == "NoSuchKey":
  52. raise ResourceNotFoundError("File not found")
  53. else:
  54. raise
  55. return generate()
  56. def download(self, filename, target_filepath):
  57. with closing(self.client) as client:
  58. client.download_file(self.bucket_name, filename, target_filepath)
  59. def exists(self, filename):
  60. with closing(self.client) as client:
  61. try:
  62. client.head_object(Bucket=self.bucket_name, Key=filename)
  63. return True
  64. except Exception:
  65. return False
  66. storage = Storage()
  67. storage.init()