garvitcpp commited on
Commit
29116ca
·
verified ·
1 Parent(s): 1459e92

Update app/services/storage_service.py

Browse files
Files changed (1) hide show
  1. app/services/storage_service.py +119 -112
app/services/storage_service.py CHANGED
@@ -1,112 +1,119 @@
1
- from appwrite.client import Client
2
- from appwrite.services.storage import Storage
3
- from appwrite.input_file import InputFile
4
- from appwrite.exception import AppwriteException
5
- from fastapi import UploadFile, HTTPException
6
- from datetime import datetime, timedelta
7
- import uuid
8
- import os
9
- from typing import Dict, Any
10
- from ..config import settings
11
- from ..utils.validators import validate_file_extension, validate_file_size
12
-
13
- class StorageService:
14
- def __init__(self):
15
- try:
16
- self.client = Client()
17
- self.client.set_endpoint(settings.APPWRITE_ENDPOINT)
18
- self.client.set_project(settings.APPWRITE_PROJECT_ID)
19
- self.client.set_key(settings.APPWRITE_API_KEY)
20
- self.storage = Storage(self.client)
21
- except Exception as e:
22
- raise HTTPException(
23
- status_code=500,
24
- detail=f"Failed to initialize storage service: {str(e)}"
25
- )
26
-
27
- def _get_expiration_seconds(self, expiration_time: str) -> int:
28
- expiration_map = {
29
- "30s": 30,
30
- "24h": 86400,
31
- "3d": 259200,
32
- "5d": 432000,
33
- "7d": 604800
34
- }
35
- return expiration_map.get(expiration_time, 86400)
36
-
37
- async def upload_file(self, file: UploadFile, expiration_time: str) -> Dict[str, Any]:
38
- try:
39
- validate_file_extension(file.filename)
40
- contents = await file.read()
41
- validate_file_size(len(contents))
42
-
43
- _, ext = os.path.splitext(file.filename)
44
- file_id = f"{uuid.uuid4().hex[:8]}{ext}"
45
-
46
- expiration_seconds = self._get_expiration_seconds(expiration_time)
47
- expiration = datetime.now() + timedelta(seconds=expiration_seconds)
48
-
49
- result = self.storage.create_file(
50
- bucket_id=settings.APPWRITE_BUCKET_ID,
51
- file_id=file_id,
52
- file=InputFile.from_bytes(contents, file.filename),
53
- permissions=['read("any")']
54
- )
55
-
56
- new_file_name = f"{file_id}__exp_{expiration.isoformat()}"
57
- self.storage.update_file(
58
- bucket_id=settings.APPWRITE_BUCKET_ID,
59
- file_id=file_id,
60
- name=new_file_name,
61
- permissions=['read("any")']
62
- )
63
-
64
- url = f"{settings.APPWRITE_ENDPOINT}/storage/buckets/{settings.APPWRITE_BUCKET_ID}/files/{file_id}/view?project={settings.APPWRITE_PROJECT_ID}"
65
-
66
- return {
67
- 'file_id': file_id,
68
- 'url': url,
69
- 'expiration': expiration.isoformat(),
70
- 'original_name': file.filename
71
- }
72
-
73
- except HTTPException as e:
74
- raise e
75
- except Exception as e:
76
- raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}")
77
- finally:
78
- await file.seek(0)
79
-
80
- async def cleanup_expired_files(self):
81
- try:
82
- files = self.storage.list_files(settings.APPWRITE_BUCKET_ID)
83
- now = datetime.now()
84
-
85
- for file in files['files']:
86
- try:
87
- file_name = file['name']
88
- if '__exp_' in file_name:
89
- _, exp_str = file_name.split('__exp_')
90
- expiration = datetime.fromisoformat(exp_str)
91
- if now > expiration:
92
- self.storage.delete_file(
93
- bucket_id=settings.APPWRITE_BUCKET_ID,
94
- file_id=file['$id']
95
- )
96
- print(f"Deleted expired file: {file['$id']}")
97
- except Exception as e:
98
- print(f"Error processing file {file['$id']}: {str(e)}")
99
- continue
100
-
101
- except Exception as e:
102
- print(f"Error during cleanup: {str(e)}")
103
-
104
- async def get_file_info(self, file_id: str) -> Dict[str, Any]:
105
- try:
106
- file = self.storage.get_file(
107
- bucket_id=settings.APPWRITE_BUCKET_ID,
108
- file_id=file_id
109
- )
110
- return file
111
- except AppwriteException as e:
112
- raise HTTPException(status_code=404, detail="File not found")
 
 
 
 
 
 
 
 
1
+ from appwrite.client import Client
2
+ from appwrite.services.storage import Storage
3
+ from appwrite.input_file import InputFile
4
+ from appwrite.exception import AppwriteException
5
+ from fastapi import UploadFile, HTTPException
6
+ from datetime import datetime, timedelta
7
+ import uuid
8
+ import os
9
+ from typing import Dict, Any
10
+ from ..config import settings
11
+ from ..utils.validators import validate_file_extension, validate_file_size
12
+ import logging
13
+
14
+ cclass StorageService:
15
+ def __init__(self):
16
+ try:
17
+ self.client = Client()
18
+ self.client.set_endpoint(settings.APPWRITE_ENDPOINT)
19
+ self.client.set_project(settings.APPWRITE_PROJECT_ID)
20
+ self.client.set_key(settings.APPWRITE_API_KEY)
21
+ self.storage = Storage(self.client)
22
+ logging.info("StorageService initialized successfully")
23
+ except Exception as e:
24
+ logging.error(f"Failed to initialize storage service: {str(e)}")
25
+ raise HTTPException(status_code=500, detail=f"Failed to initialize storage service: {str(e)}")
26
+
27
+ def _get_expiration_seconds(self, expiration_time: str) -> int:
28
+ expiration_map = {
29
+ "30s": 30,
30
+ "24h": 86400,
31
+ "3d": 259200,
32
+ "5d": 432000,
33
+ "7d": 604800
34
+ }
35
+ return expiration_map.get(expiration_time, 86400)
36
+
37
+ async def upload_file(self, file: UploadFile, expiration_time: str) -> Dict[str, Any]:
38
+ try:
39
+ validate_file_extension(file.filename)
40
+ contents = await file.read()
41
+ validate_file_size(len(contents))
42
+
43
+ _, ext = os.path.splitext(file.filename)
44
+ file_id = f"{uuid.uuid4().hex[:8]}{ext}"
45
+
46
+ expiration_seconds = self._get_expiration_seconds(expiration_time)
47
+ expiration = datetime.now() + timedelta(seconds=expiration_seconds)
48
+
49
+ result = self.storage.create_file(
50
+ bucket_id=settings.APPWRITE_BUCKET_ID,
51
+ file_id=file_id,
52
+ file=InputFile.from_bytes(contents, file.filename),
53
+ permissions=['read("any")']
54
+ )
55
+
56
+ new_file_name = f"{file_id}__exp_{expiration.isoformat()}"
57
+ self.storage.update_file(
58
+ bucket_id=settings.APPWRITE_BUCKET_ID,
59
+ file_id=file_id,
60
+ name=new_file_name,
61
+ permissions=['read("any")']
62
+ )
63
+
64
+ url = f"{settings.APPWRITE_ENDPOINT}/storage/buckets/{settings.APPWRITE_BUCKET_ID}/files/{file_id}/view?project={settings.APPWRITE_PROJECT_ID}"
65
+
66
+ return {
67
+ 'file_id': file_id,
68
+ 'url': url,
69
+ 'expiration': expiration.isoformat(),
70
+ 'original_name': file.filename
71
+ }
72
+
73
+ except HTTPException as e:
74
+ raise e
75
+ except Exception as e:
76
+ raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}")
77
+ finally:
78
+ await file.seek(0)
79
+
80
+ async def cleanup_expired_files(self):
81
+ logging.info("Starting cleanup of expired files")
82
+ try:
83
+ files = self.storage.list_files(settings.APPWRITE_BUCKET_ID)
84
+ logging.info(f"Found {len(files['files'])} files in the bucket")
85
+ now = datetime.now()
86
+
87
+ for file in files['files']:
88
+ try:
89
+ file_name = file['name']
90
+ file_id = file['$id']
91
+ logging.info(f"Processing file: {file_id} - {file_name}")
92
+
93
+ if '__exp_' in file_name:
94
+ _, exp_str = file_name.split('__exp_')
95
+ expiration = datetime.fromisoformat(exp_str)
96
+ logging.info(f"File expiration: {expiration}, Current time: {now}")
97
+
98
+ if now > expiration:
99
+ logging.info(f"Deleting expired file: {file_id}")
100
+ self.storage.delete_file(
101
+ bucket_id=settings.APPWRITE_BUCKET_ID,
102
+ file_id=file_id
103
+ )
104
+ logging.info(f"Successfully deleted expired file: {file_id}")
105
+ else:
106
+ logging.info(f"File {file_id} not yet expired")
107
+ else:
108
+ logging.warning(f"File {file_id} does not have expiration info in its name")
109
+
110
+ except Exception as e:
111
+ logging.error(f"Error processing file {file_id}: {str(e)}")
112
+ continue
113
+
114
+ logging.info("Cleanup process completed")
115
+
116
+ except AppwriteException as e:
117
+ logging.error(f"Appwrite error during cleanup: {str(e)}")
118
+ except Exception as e:
119
+ logging.error(f"Unexpected error during cleanup: {str(e)}")