patharanor commited on
Commit
38c614d
·
1 Parent(s): 04f0937

feat: upload stepping

Browse files
Files changed (2) hide show
  1. app.py +157 -92
  2. requirements.txt +1 -0
app.py CHANGED
@@ -1,7 +1,9 @@
1
  import boto3
 
2
  import gradio as gr
3
  import os
4
  from dotenv import load_dotenv
 
5
  load_dotenv()
6
 
7
  ACCOUNT_ID = os.getenv('AWS_ACCOUNT_ID', '')
@@ -12,6 +14,8 @@ AWS_S3_BUCKET_NAME = os.getenv('AWS_S3_BUCKET_NAME', '')
12
 
13
  is_dev = os.environ.get('ENV', 'DEV') != 'PROD'
14
 
 
 
15
  s3_client = boto3.client(
16
  service_name='s3',
17
  region_name=AWS_DEFAULT_REGION,
@@ -24,6 +28,14 @@ def auth(username, password):
24
  p = os.environ.get('PASSWORD')
25
  return (username == u and password == p)
26
 
 
 
 
 
 
 
 
 
27
  # Function to list images in a specific S3 bucket
28
  def list_images_in_bucket(bucket_name):
29
  response = s3_client.list_objects_v2(Bucket=bucket_name)
@@ -35,36 +47,73 @@ def get_image_urls(bucket_name, image_keys):
35
 
36
  # Function to upload files to S3
37
  def upload_files(files, progress=gr.Progress()):
38
- for file in progress.tqdm(files, desc="Uploading..."):
39
- file_name = os.path.basename(file.name)
40
- with open(file.name, 'rb') as f:
41
- print(f'Uploading "{file_name}"...')
42
- s3_client.upload_fileobj(f, AWS_S3_BUCKET_NAME, file_name)
43
-
44
- return display_images()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  # Function to fetch and display images
47
- def display_images():
48
- image_keys = list_images_in_bucket(AWS_S3_BUCKET_NAME)
49
- image_urls = get_image_urls(AWS_S3_BUCKET_NAME, image_keys)
50
- # print(image_keys)
51
- # print(image_urls)
52
- return image_urls, image_keys
 
 
 
 
 
 
53
 
54
  # Function to delete a file from S3
55
- def delete_image(file_key):
56
- if isinstance(file_key, list):
57
- for k in file_key:
58
- print(f'Removing "{k}"...')
59
- s3_client.delete_object(Bucket=AWS_S3_BUCKET_NAME, Key=k)
60
- else:
61
- s3_client.delete_object(Bucket=AWS_S3_BUCKET_NAME, Key=file_key)
62
- return display_images()
 
 
 
 
 
 
 
63
 
64
- def update_dropdown_image(evt: gr.SelectData):
 
 
65
  # print(f"You selected {evt.value} at {evt.index} from {evt.target}")
66
  # print(f"You selected {evt.value['image']['orig_name']}")
67
- return evt.value['image']['orig_name']
68
 
69
  # ---------------------------------------------------------------------------
70
 
@@ -77,80 +126,96 @@ def list_files_in_bucket(bucket_name):
77
  def get_files_urls(bucket_name, file_keys):
78
  return [s3_client.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': key}) for key in file_keys]
79
 
80
- # Function to fetch and display files
81
- def display_files():
82
- file_keys = list_files_in_bucket(AWS_S3_BUCKET_NAME)
83
- file_urls = get_files_urls(AWS_S3_BUCKET_NAME, file_keys)
84
- # print(file_keys)
85
- # print(file_urls)
86
- return file_urls, file_keys
87
-
88
- # Function to delete a file from S3
89
- def delete_files(file_key):
90
- if isinstance(file_key, list):
91
- for k in file_key:
92
- print(f'Removing "{k}"...')
93
- s3_client.delete_object(Bucket=AWS_S3_BUCKET_NAME, Key=k)
94
  else:
95
- s3_client.delete_object(Bucket=AWS_S3_BUCKET_NAME, Key=file_key)
96
- return display_files()
97
-
98
- def update_dropdown_files(evt: gr.SelectData):
99
- #print(f"You selected {evt.value} at {evt.index} from {evt.target}")
100
- return evt.value.split('AWSAccessKeyId')[0]
101
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  # Create a Gradio interface
103
  with gr.Blocks() as demo:
104
 
105
  gr.Markdown("# **Data collector**")
106
-
107
- with gr.Row():
108
- with gr.Column(scale=1):
109
- gr.Markdown("""## **1. Upload files**
110
-
111
- 1. โยนไฟล์ (drag/drop) ไปยัง ***ไฟล์ list ทาง panel ทางด้านซ้าย*** ได้มากกว่า 1 ไฟล์
112
- 2. กด **Upload Files**
113
- """)
114
- file_uploader = gr.File(label="Upload Images", file_count="multiple", height=400)
115
- upload_btn = gr.Button("Upload Files")
116
-
117
- with gr.Column(scale=3):
118
- with gr.Tabs():
119
- with gr.Tab('Images'):
120
- gr.Markdown("""## **2. Load images**
121
- กดที่ **Refresh Gallery**
122
- """)
123
- img_gallery = gr.Gallery(label="Images from S3", columns=9, height=600, interactive=True)
124
- img_refresh_btn = gr.Button("Refresh Gallery")
125
-
126
- gr.Markdown("""### ***Delete images***
127
- กรณีต้องการลบไฟล์ ท่านสามารถเลือกภาพที่สนใจ แล้วกด **Delete Selected Files** แต่ถ้าต้องการลบมากกว่า 1 file ให้ใส่ชื่อไฟล์ คั่นด้วย comma (,)
128
- """)
129
- img_selected_image = gr.Dropdown(choices=[], label="Select Image to Delete", allow_custom_value=True)
130
- img_delete_btn = gr.Button("Delete Selected Files")
131
-
132
- with gr.Tab('Files'):
133
- gr.Markdown("""## **2. Load files**
134
- กดที่ **Refresh Gallery**
135
- """)
136
- file_gallery = gr.File(label="Files from S3", interactive=True)
137
- file_refresh_btn = gr.Button("Refresh Gallery")
138
-
139
- gr.Markdown("""### ***Delete files***
140
- กรณีต้องการลบไฟล์ ท่านสามารถเลือกภาพที่สนใจ แล้วกด **Delete Selected Files** แต่ถ้าต้องการลบมากกว่า 1 file ให้ใส่ชื่อไฟล์ คั่นด้วย comma (,)
141
- """)
142
- file_selected = gr.Dropdown(choices=[], label="Select File to Delete", allow_custom_value=True)
143
- file_delete_btn = gr.Button("Delete Selected Files")
144
-
145
- upload_btn.click(fn=upload_files, inputs=[file_uploader], outputs=[img_gallery, img_selected_image])
146
-
147
- img_refresh_btn.click(fn=display_images, outputs=[img_gallery, img_selected_image])
148
- img_delete_btn.click(fn=delete_image, inputs=img_selected_image, outputs=[img_gallery, img_selected_image])
149
- img_gallery.select(fn=update_dropdown_image, outputs=img_selected_image)
150
-
151
- file_refresh_btn.click(fn=display_files, outputs=[file_gallery, file_selected])
152
- file_delete_btn.click(fn=delete_files, inputs=file_selected, outputs=[file_gallery, file_selected])
153
- file_gallery.select(fn=update_dropdown_files, outputs=file_selected)
 
 
 
 
 
154
 
155
  # Launch the Gradio app
156
  demo.launch(auth=auth if not is_dev else None)
 
1
  import boto3
2
+ import botocore
3
  import gradio as gr
4
  import os
5
  from dotenv import load_dotenv
6
+ import pandas as pd
7
  load_dotenv()
8
 
9
  ACCOUNT_ID = os.getenv('AWS_ACCOUNT_ID', '')
 
14
 
15
  is_dev = os.environ.get('ENV', 'DEV') != 'PROD'
16
 
17
+ job_no = ''
18
+ selected_file_index = 0
19
  s3_client = boto3.client(
20
  service_name='s3',
21
  region_name=AWS_DEFAULT_REGION,
 
28
  p = os.environ.get('PASSWORD')
29
  return (username == u and password == p)
30
 
31
+ def set_key(key, prefix=''):
32
+ return f'{prefix}/{key}' if len(prefix) > 0 else key
33
+
34
+ # Function to list files in S3 bucket
35
+ def list_object_in_bucket(bucket_name, prefix=''):
36
+ response = s3_client.list_objects_v2(Bucket=bucket_name, Prefix=prefix)
37
+ return [obj['Key'] for obj in response.get('Contents', [])]
38
+
39
  # Function to list images in a specific S3 bucket
40
  def list_images_in_bucket(bucket_name):
41
  response = s3_client.list_objects_v2(Bucket=bucket_name)
 
47
 
48
  # Function to upload files to S3
49
  def upload_files(files, progress=gr.Progress()):
50
+ global job_no
51
+ req_id = os.environ.get('USERNAME')
52
+ try:
53
+ for file in progress.tqdm(files, desc="Uploading..."):
54
+ file_name = os.path.basename(file.name)
55
+ with open(file.name, 'rb') as f:
56
+ print(f' - Uploading "{file_name}" to "{job_no}"...')
57
+ # s3_client.upload_fileobj(f, AWS_S3_BUCKET_NAME, file_name)
58
+
59
+ key = set_key(file_name, job_no)
60
+ s3_client.put_object(
61
+ Body=f,
62
+ Bucket=AWS_S3_BUCKET_NAME,
63
+ Key=key,
64
+ Metadata={
65
+ 'x-request-id': req_id,
66
+ })
67
+
68
+ print('Done')
69
+
70
+ except botocore.exceptions.ClientError as error:
71
+ if error.response['Error']['Code'] == 'LimitExceededException':
72
+ print('API call limit exceeded; backing off and retrying...')
73
+ else:
74
+ print(error)
75
+ except botocore.exceptions.ParamValidationError as error:
76
+ print('The parameters you provided are incorrect: {}'.format(error))
77
+
78
+ return display_images(job_no)
79
 
80
  # Function to fetch and display images
81
+ def display_images(job_no):
82
+ # image_keys = list_images_in_bucket(AWS_S3_BUCKET_NAME)
83
+ # image_urls = get_image_urls(AWS_S3_BUCKET_NAME, image_keys)
84
+ # # print(image_keys)
85
+ # # print(image_urls)
86
+
87
+ # return None, image_urls, image_keys
88
+
89
+ return None, \
90
+ pd.DataFrame({
91
+ "keys": list_object_in_bucket(AWS_S3_BUCKET_NAME, job_no)
92
+ })
93
 
94
  # Function to delete a file from S3
95
+ def delete_image(file_key, search_fpath):
96
+ try:
97
+ if isinstance(file_key, list):
98
+ for k in file_key:
99
+ print(f'Removing "{k}" from list...')
100
+ s3_client.delete_object(Bucket=AWS_S3_BUCKET_NAME, Key=k)
101
+ else:
102
+ print(f'Removing "{file_key}"...')
103
+ s3_client.delete_object(Bucket=AWS_S3_BUCKET_NAME, Key=file_key)
104
+ except Exception as e:
105
+ print(f'Error delete_image: {str(e)}')
106
+
107
+ image_keys = list_object_in_bucket(AWS_S3_BUCKET_NAME, search_fpath)
108
+ if len(image_keys) == 0:
109
+ image_keys = []
110
 
111
+ return pd.DataFrame({ "keys": image_keys }), image_keys
112
+
113
+ def update_dropdown_image(search_fpath, evt: gr.SelectData):
114
  # print(f"You selected {evt.value} at {evt.index} from {evt.target}")
115
  # print(f"You selected {evt.value['image']['orig_name']}")
116
+ return set_key(evt.value['image']['orig_name'], search_fpath)
117
 
118
  # ---------------------------------------------------------------------------
119
 
 
126
  def get_files_urls(bucket_name, file_keys):
127
  return [s3_client.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': key}) for key in file_keys]
128
 
129
+ def onchange_job_no(v):
130
+ global job_no
131
+ job_no = v
132
+ if len(v) > 0:
133
+ isinteractive = True
134
+ isempty = False
 
 
 
 
 
 
 
 
135
  else:
136
+ isinteractive = False
137
+ isempty = True
138
+
139
+ return gr.Button("ยืนยัน job no.", interactive=isinteractive), \
140
+ gr.File(label="Upload Images", file_count="multiple", height=400, interactive=(not isempty and not isinteractive)), \
141
+ gr.Button("Upload Files", interactive=(not isempty and not isinteractive))
142
+
143
+ def onclick_confirm_job_no():
144
+ global job_no
145
+ return gr.Button("ยืนยัน job no.", interactive=False), \
146
+ gr.File(label="Upload Images", file_count="multiple", height=400, interactive=True), \
147
+ gr.Button("Upload Files", interactive=True), \
148
+ job_no
149
+
150
+ def onselect_file(files, evt: gr.SelectData):
151
+ global selected_file_index
152
+ selected_file_index = evt.index[0]
153
+ fpath = files.iloc[selected_file_index]
154
+ file_urls = get_files_urls(AWS_S3_BUCKET_NAME, fpath)
155
+ return file_urls[0]
156
+
157
+ def onclick_search_by_key(prefix):
158
+ image_keys = list_object_in_bucket(AWS_S3_BUCKET_NAME, prefix)
159
+ gallery = get_image_urls(AWS_S3_BUCKET_NAME, image_keys)
160
+ return pd.DataFrame({ "keys": image_keys }), gallery
161
+
162
  # Create a Gradio interface
163
  with gr.Blocks() as demo:
164
 
165
  gr.Markdown("# **Data collector**")
166
+
167
+ with gr.Tabs():
168
+ with gr.Tab('Upload'):
169
+ with gr.Column():
170
+ gr.Markdown("""## **1. กำหนด job no.**
171
+
172
+ เพื่อใช้ในการอ้างอิงหรือเชื่อมโยงกลุ่มของข้อมูลที่ทำการ upload ขึ้นมา
173
+ """)
174
+ job_no = gr.Textbox('', label='Job no.')
175
+ set_job_no_btn = gr.Button("ยืนยัน job no.", interactive=False)
176
+
177
+ with gr.Column():
178
+ gr.Markdown("""## **2. Upload files**
179
+
180
+ 1. โยนไฟล์ (drag/drop) ไปยัง ***ไฟล์ list ทาง panel ทางด้านซ้าย*** ได้มากกว่า 1 ไฟล์
181
+ 2. กด **Upload Files**
182
+ """)
183
+ file_uploader = gr.File(label="Upload Images", file_count="multiple", height=400, interactive=False)
184
+ upload_btn = gr.Button("Upload Files", interactive=False)
185
+
186
+ with gr.Tab('Preview'):
187
+ with gr.Row():
188
+ with gr.Column(scale=2):
189
+ search_fpath = gr.Textbox('', label='Job no.')
190
+ search_btn = gr.Button("Search")
191
+ files_in_bucket = gr.Dataframe(label='Files', height=600)
192
+
193
+ with gr.Column(scale=4):
194
+ with gr.Tabs():
195
+ with gr.Tab('Image'):
196
+ image = gr.Image()
197
+
198
+ with gr.Tab('Gallery'):
199
+ gr.Markdown("""
200
+ กดที่ **Refresh Gallery** เพื่อดูข้อมูลของ job no. นั้นๆ
201
+ """)
202
+ img_gallery = gr.Gallery(label="Images from S3", columns=9, height=600, interactive=True)
203
+
204
+ gr.Markdown("""### ***Delete images***
205
+ กรณีต้องการลบไฟล์ ท่านสามารถเลือกภาพที่สนใจ แล้วกด **Delete Selected Files** แต่ถ้าต้องการลบมากกว่า 1 file ให้ใส่ชื่อไฟล์ คั่นด้วย comma (,)
206
+ """)
207
+ img_selected_image = gr.Dropdown(choices=[], label="Select Image to Delete", allow_custom_value=True)
208
+ img_delete_btn = gr.Button("Delete Selected Files")
209
+
210
+ job_no.change(fn=onchange_job_no, inputs=[job_no], outputs=[set_job_no_btn, file_uploader, upload_btn])
211
+ set_job_no_btn.click(fn=onclick_confirm_job_no, inputs=[], outputs=[set_job_no_btn, file_uploader, upload_btn, search_fpath])
212
+ upload_btn.click(fn=upload_files, inputs=[file_uploader], outputs=[file_uploader, files_in_bucket])# img_gallery, img_selected_image])
213
+
214
+ img_delete_btn.click(fn=delete_image, inputs=[img_selected_image, search_fpath], outputs=[img_gallery, img_selected_image])
215
+ img_gallery.select(fn=update_dropdown_image, inputs=[search_fpath], outputs=img_selected_image)
216
+
217
+ search_btn.click(fn=onclick_search_by_key, inputs=[search_fpath], outputs=[files_in_bucket, img_gallery])
218
+ files_in_bucket.select(fn=onselect_file, inputs=[files_in_bucket], outputs=[image])
219
 
220
  # Launch the Gradio app
221
  demo.launch(auth=auth if not is_dev else None)
requirements.txt CHANGED
@@ -1,4 +1,5 @@
1
  boto3
 
2
  gradio
3
  pillow
4
  python-dotenv
 
1
  boto3
2
+ botocore
3
  gradio
4
  pillow
5
  python-dotenv