storage.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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(Filename=local_file_path, Bucket=self.bucket_name, Key=filename)
  24. def load(self, filename: str, stream: bool = False) -> Union[bytes, Generator]:
  25. if stream:
  26. return self.load_stream(filename)
  27. else:
  28. return self.load_once(filename)
  29. def load_once(self, filename: str) -> bytes:
  30. try:
  31. with closing(self.client) as client:
  32. data = client.get_object(Bucket=self.bucket_name, Key=filename)["Body"].read()
  33. except ClientError as ex:
  34. if ex.response["Error"]["Code"] == "NoSuchKey":
  35. raise ResourceNotFoundError("File not found")
  36. else:
  37. raise
  38. return data
  39. def load_stream(self, filename: str) -> Generator:
  40. def generate(filename: str = filename) -> Generator:
  41. try:
  42. with closing(self.client) as client:
  43. response = client.get_object(Bucket=self.bucket_name, Key=filename)
  44. for chunk in response["Body"].iter_chunks():
  45. yield chunk
  46. except ClientError as ex:
  47. if ex.response["Error"]["Code"] == "NoSuchKey":
  48. raise ResourceNotFoundError("File not found")
  49. else:
  50. raise
  51. return generate()
  52. def download(self, filename, target_filepath):
  53. with closing(self.client) as client:
  54. client.download_file(self.bucket_name, filename, target_filepath)
  55. def exists(self, filename):
  56. with closing(self.client) as client:
  57. try:
  58. client.head_object(Bucket=self.bucket_name, Key=filename)
  59. return True
  60. except Exception:
  61. return False
  62. storage = Storage()
  63. storage.init()