ABAO77 commited on
Commit
0e33a02
·
verified ·
1 Parent(s): 5cce605

Upload 25 files

Browse files
Files changed (2) hide show
  1. src/.DS_Store +0 -0
  2. src/firebase/firebase_provider.py +64 -45
src/.DS_Store CHANGED
Binary files a/src/.DS_Store and b/src/.DS_Store differ
 
src/firebase/firebase_provider.py CHANGED
@@ -6,7 +6,7 @@ from PIL import Image
6
  import io
7
  import aiofiles
8
  import asyncio
9
- from typing import List
10
  from datetime import datetime
11
  import pytz
12
 
@@ -14,14 +14,15 @@ import pytz
14
  import asyncio
15
  import functools
16
 
 
17
  def upload_file_to_storage_sync(file_path, file_name):
18
  """
19
  Synchronous function to upload a file to Firebase Storage.
20
-
21
  param:
22
  file_path: str - The path of the file on the local machine to be uploaded.
23
  file_name: str - The name of the file in Firebase Storage.
24
-
25
  return:
26
  str - The public URL of the uploaded file.
27
  """
@@ -31,26 +32,28 @@ def upload_file_to_storage_sync(file_path, file_name):
31
 
32
  return blob.public_url
33
 
 
34
  async def upload_file_to_storage(file_path: str, file_name: str) -> str:
35
  """
36
  Asynchronous wrapper to upload a file to Firebase Storage using a thread pool.
37
-
38
  param:
39
  file_path: str - The path of the file on the local machine to be uploaded.
40
  file_name: str - The name of the file in Firebase Storage.
41
-
42
  return:
43
  str - The public URL of the uploaded file.
44
  """
45
  loop = asyncio.get_event_loop()
46
 
47
  # Run the synchronous `upload_file_to_storage_sync` in a thread pool.
48
- public_url = await loop.run_in_executor(None, functools.partial(upload_file_to_storage_sync, file_path, file_name))
 
 
49
 
50
  return public_url
51
 
52
 
53
-
54
  def delete_file_from_storage(file_name):
55
  """
56
  Delete a file from Firebase Storage
@@ -98,60 +101,76 @@ def download_file_from_storage(file_name, destination_path):
98
  return False
99
 
100
 
101
- async def upload_base64_image_to_storage(base64_image: str, file_name: str) -> str:
 
 
102
  """
103
- Upload a base64 image to Firebase Storage.
104
-
105
- param:
106
- base64_image: str - The base64 encoded image.
107
- file_name: str - The name of the file to be uploaded.
108
-
109
- return:
110
- str - The public URL of the uploaded file.
111
  """
112
  try:
113
- # Decode the base64 image
114
- image_data = base64.b64decode(base64_image)
 
 
 
 
 
115
 
116
- # Convert the decoded image to a JPG file
117
- image = Image.open(io.BytesIO(image_data))
118
-
119
- # Generate a temporary file path
120
- temp_file_path = f"{tempfile.gettempdir()}/{file_name}.jpg"
121
 
122
- # Since image.save is a blocking operation, run it in a thread pool
123
- loop = asyncio.get_event_loop()
124
- await loop.run_in_executor(None, lambda: image.save(temp_file_path, format="JPEG"))
 
125
 
126
- # Upload the JPG file to Firebase Storage
127
- public_url = await upload_file_to_storage(temp_file_path, f"{file_name}.jpg")
 
 
128
 
129
- # Remove the temporary file
130
- os.remove(temp_file_path)
 
 
 
 
 
 
 
131
 
132
- return public_url
133
  except Exception as e:
134
- print("Error:", e)
135
  return None
136
 
137
- async def process_images(base64_images: list) -> list:
 
 
 
 
 
 
 
 
 
 
138
  tasks = []
139
  for idx, base64_image in enumerate(base64_images):
140
  timestamp = (
141
  datetime.now(pytz.timezone("Asia/Ho_Chi_Minh"))
142
  .replace(tzinfo=None)
143
- .strftime("%Y-%m-%d %H:%M:%S")
144
  )
145
- encoded_timestamp = (
146
- base64.urlsafe_b64encode(timestamp.encode()).decode().rstrip("=")
147
- )
148
- file_name = f"image_{encoded_timestamp}_{idx}"
149
  tasks.append(upload_base64_image_to_storage(base64_image, file_name))
150
 
151
- # Gather all async tasks
152
- final_output = await asyncio.gather(*tasks)
153
-
154
- # Check the output for debugging
155
- print("final_output", final_output) # Print the final output for debugging
156
-
157
- return final_output
 
6
  import io
7
  import aiofiles
8
  import asyncio
9
+ from typing import List, Optional
10
  from datetime import datetime
11
  import pytz
12
 
 
14
  import asyncio
15
  import functools
16
 
17
+
18
  def upload_file_to_storage_sync(file_path, file_name):
19
  """
20
  Synchronous function to upload a file to Firebase Storage.
21
+
22
  param:
23
  file_path: str - The path of the file on the local machine to be uploaded.
24
  file_name: str - The name of the file in Firebase Storage.
25
+
26
  return:
27
  str - The public URL of the uploaded file.
28
  """
 
32
 
33
  return blob.public_url
34
 
35
+
36
  async def upload_file_to_storage(file_path: str, file_name: str) -> str:
37
  """
38
  Asynchronous wrapper to upload a file to Firebase Storage using a thread pool.
39
+
40
  param:
41
  file_path: str - The path of the file on the local machine to be uploaded.
42
  file_name: str - The name of the file in Firebase Storage.
43
+
44
  return:
45
  str - The public URL of the uploaded file.
46
  """
47
  loop = asyncio.get_event_loop()
48
 
49
  # Run the synchronous `upload_file_to_storage_sync` in a thread pool.
50
+ public_url = await loop.run_in_executor(
51
+ None, functools.partial(upload_file_to_storage_sync, file_path, file_name)
52
+ )
53
 
54
  return public_url
55
 
56
 
 
57
  def delete_file_from_storage(file_name):
58
  """
59
  Delete a file from Firebase Storage
 
101
  return False
102
 
103
 
104
+ async def upload_base64_image_to_storage(
105
+ base64_image: str, file_name: str
106
+ ) -> Optional[str]:
107
  """
108
+ Upload a base64 image to Firebase Storage asynchronously.
109
+
110
+ Args:
111
+ base64_image: str - The base64 encoded image
112
+ file_name: str - The name of the file to be uploaded
113
+
114
+ Returns:
115
+ Optional[str] - The public URL of the uploaded file or None if failed
116
  """
117
  try:
118
+ # Run CPU-intensive operations in thread pool
119
+ loop = asyncio.get_event_loop()
120
+
121
+ # Decode base64 in thread pool
122
+ image_data = await loop.run_in_executor(
123
+ None, lambda: base64.b64decode(base64_image)
124
+ )
125
 
126
+ # Open and process image in thread pool
127
+ image = await loop.run_in_executor(
128
+ None, lambda: Image.open(io.BytesIO(image_data))
129
+ )
 
130
 
131
+ # Create unique temp file path
132
+ temp_file_path = os.path.join(
133
+ tempfile.gettempdir(), f"{file_name}_{datetime.now().timestamp()}.jpg"
134
+ )
135
 
136
+ # Save image in thread pool
137
+ await loop.run_in_executor(
138
+ None, lambda: image.save(temp_file_path, format="JPEG")
139
+ )
140
 
141
+ try:
142
+ # Upload to Firebase
143
+ public_url = await upload_file_to_storage(
144
+ temp_file_path, f"{file_name}.jpg"
145
+ )
146
+ return public_url
147
+ finally:
148
+ # Clean up temp file in thread pool
149
+ await loop.run_in_executor(None, os.remove, temp_file_path)
150
 
 
151
  except Exception as e:
152
+ print(f"Error processing image {file_name}: {str(e)}")
153
  return None
154
 
155
+
156
+ async def process_images(base64_images: List[str]) -> List[Optional[str]]:
157
+ """
158
+ Process multiple base64 images concurrently.
159
+
160
+ Args:
161
+ base64_images: List[str] - List of base64 encoded images
162
+
163
+ Returns:
164
+ List[Optional[str]] - List of public URLs or None for failed uploads
165
+ """
166
  tasks = []
167
  for idx, base64_image in enumerate(base64_images):
168
  timestamp = (
169
  datetime.now(pytz.timezone("Asia/Ho_Chi_Minh"))
170
  .replace(tzinfo=None)
171
+ .strftime("%Y-%m-%d_%H-%M-%S")
172
  )
173
+ file_name = f"image_{timestamp}_{idx}"
 
 
 
174
  tasks.append(upload_base64_image_to_storage(base64_image, file_name))
175
 
176
+ return await asyncio.gather(*tasks, return_exceptions=True)