You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

s3_storage.py 2.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. from collections.abc import Generator
  2. from contextlib import closing
  3. import boto3
  4. from botocore.client import Config
  5. from botocore.exceptions import ClientError
  6. from flask import Flask
  7. from extensions.storage.base_storage import BaseStorage
  8. class S3Storage(BaseStorage):
  9. """Implementation for s3 storage.
  10. """
  11. def __init__(self, app: Flask):
  12. super().__init__(app)
  13. app_config = self.app.config
  14. self.bucket_name = app_config.get('S3_BUCKET_NAME')
  15. self.client = boto3.client(
  16. 's3',
  17. aws_secret_access_key=app_config.get('S3_SECRET_KEY'),
  18. aws_access_key_id=app_config.get('S3_ACCESS_KEY'),
  19. endpoint_url=app_config.get('S3_ENDPOINT'),
  20. region_name=app_config.get('S3_REGION'),
  21. config=Config(s3={'addressing_style': app_config.get('S3_ADDRESS_STYLE')})
  22. )
  23. def save(self, filename, data):
  24. self.client.put_object(Bucket=self.bucket_name, Key=filename, Body=data)
  25. def load_once(self, filename: str) -> bytes:
  26. try:
  27. with closing(self.client) as client:
  28. data = client.get_object(Bucket=self.bucket_name, Key=filename)['Body'].read()
  29. except ClientError as ex:
  30. if ex.response['Error']['Code'] == 'NoSuchKey':
  31. raise FileNotFoundError("File not found")
  32. else:
  33. raise
  34. return data
  35. def load_stream(self, filename: str) -> Generator:
  36. def generate(filename: str = filename) -> Generator:
  37. try:
  38. with closing(self.client) as client:
  39. response = client.get_object(Bucket=self.bucket_name, Key=filename)
  40. yield from response['Body'].iter_chunks()
  41. except ClientError as ex:
  42. if ex.response['Error']['Code'] == 'NoSuchKey':
  43. raise FileNotFoundError("File not found")
  44. else:
  45. raise
  46. return generate()
  47. def download(self, filename, target_filepath):
  48. with closing(self.client) as client:
  49. client.download_file(self.bucket_name, filename, target_filepath)
  50. def exists(self, filename):
  51. with closing(self.client) as client:
  52. try:
  53. client.head_object(Bucket=self.bucket_name, Key=filename)
  54. return True
  55. except:
  56. return False
  57. def delete(self, filename):
  58. self.client.delete_object(Bucket=self.bucket_name, Key=filename)