From a80947d89228658bdb7e7adc4bf91bdc951a5923 Mon Sep 17 00:00:00 2001 From: Kentai Radiquum <kentai.waah@gmail.com> Date: Mon, 17 Feb 2025 20:56:42 +0500 Subject: [PATCH] feat/admin: early return if file already exists --- admin/main.py | 68 ++++++++++++++++++++++++++++--------- admin/requirements.txt | 2 +- admin/templates/Upload.html | 20 +++++++---- 3 files changed, 66 insertions(+), 24 deletions(-) diff --git a/admin/main.py b/admin/main.py index 65bd011..eb0be5d 100644 --- a/admin/main.py +++ b/admin/main.py @@ -10,7 +10,9 @@ import boto3 from botocore.client import Config from botocore.exceptions import ClientError, SSLError import firebase_admin -from firebase_admin import firestore, credentials, exceptions +from firebase_admin import firestore, credentials +from firebase_admin import exceptions as FB_EXCEPTION +from google.api_core import exceptions as GOOGLE_EXCEPTION load_dotenv() UPLOAD_FOLDER = "./temp" @@ -123,19 +125,6 @@ def ApiUpload(): ) Image = PIL.Image.open(os.path.join(app.config["UPLOAD_FOLDER"], filename)) - TMP_FILE = open(os.path.join(app.config["UPLOAD_FOLDER"], filename), "rb") - file_path = filename.split(".")[0] - file_ext = filename.split(".")[-1] - - s3OrigFileResponse = upload_file( - TMP_FILE, os.getenv("AWS_BUCKET"), f"{file_path}/{filename}", file.mimetype - ) - if s3OrigFileResponse is not True: - return Response( - json.dumps({"status": "error", "message": f"S3 ERR: {s3OrigFileResponse}"}), - 500, - ) - try: db.collection(os.getenv("PREFIX")).add( { @@ -149,9 +138,56 @@ def ApiUpload(): }, request.files["file"].filename, ) - except exceptions.CONFLICT: + except (FB_EXCEPTION.ConflictError, FB_EXCEPTION.AlreadyExistsError, GOOGLE_EXCEPTION.AlreadyExists) as e: + Image.close() + os.remove(os.path.join(app.config["UPLOAD_FOLDER"], filename)) return Response( - '{"status": "error", "message": "FIRESTORE ERR: CONFLICT"}', 400 + json.dumps({"status": "error", "message": f"FIRESTORE ERR: {e}"}), 400 ) + file_path = filename.split(".")[0] + file_ext = filename.split(".")[-1] + + temp_file = open(os.path.join(app.config["UPLOAD_FOLDER"], filename), "rb") + s3OrigFileResponse = upload_file( + temp_file, os.getenv("AWS_BUCKET"), f"{file_path}/{filename}", file.mimetype + ) + if s3OrigFileResponse is not True: + return Response( + json.dumps({"status": "error", "message": f"S3 ERR: {s3OrigFileResponse}"}), + 500, + ) + temp_file.close() + + size = 24, 24 + Image.thumbnail(size, PIL.Image.Resampling.LANCZOS) + Image.save( + os.path.join(app.config["UPLOAD_FOLDER"], f"{file_path}-24px.{file_ext}") + ) + Image.close() + + temp_file = open( + os.path.join(app.config["UPLOAD_FOLDER"], f"{file_path}-24px.{file_ext}"), "rb" + ) + s3BlurFileResponse = upload_file( + temp_file, + os.getenv("AWS_BUCKET"), + f"{file_path}/{file_path}-24px.{file_ext}", + file.mimetype, + ) + if s3BlurFileResponse is not True: + db.collection(os.getenv("PREFIX")).document( + request.files["file"].filename + ).delete() + s3.delete_object(Bucket=os.getenv("AWS_BUCKET"), Key=f"{file_path}/{filename}") + s3.delete_object(Bucket=os.getenv("AWS_BUCKET"), Key=f"{file_path}") + return Response( + json.dumps({"status": "error", "message": f"S3 ERR: {s3BlurFileResponse}"}), + 500, + ) + temp_file.close() + + os.remove(os.path.join(app.config["UPLOAD_FOLDER"], filename)) + os.remove(os.path.join(app.config["UPLOAD_FOLDER"], f"{file_path}-24px.{file_ext}")) + return {"status": "ok", "message": "Uploaded"} diff --git a/admin/requirements.txt b/admin/requirements.txt index c923232..e2b7ae7 100644 --- a/admin/requirements.txt +++ b/admin/requirements.txt @@ -1,7 +1,7 @@ python-dotenv # Load environment variables from .env boto3==1.35.99 # AWS SDK for Python (S3) -boto3-stubs[essential] +boto3-stubs[essential]==1.35.99 firebase-admin # Firebase Admin SDK for Python (FireStore) Flask # Web framework diff --git a/admin/templates/Upload.html b/admin/templates/Upload.html index 96d271e..341bf40 100644 --- a/admin/templates/Upload.html +++ b/admin/templates/Upload.html @@ -35,8 +35,8 @@ </div> <div class="flex gap-4"> - <div id="datepicker-inline" inline-datepicker datepicker-buttons - datepicker-format="dd/mm/yyyy" datepicker-title="Shoot Date" data-date="today"></div> + <div id="datepicker-inline" inline-datepicker datepicker-buttons datepicker-format="dd/mm/yyyy" + datepicker-title="Shoot Date" data-date="today"></div> <div class="w-full flex flex-col gap-4"> <div class="w-full"> <label for="tags-input" @@ -184,7 +184,6 @@ }); form.addEventListener('submit', (e) => { e.preventDefault(); - btnSubmit.disabled = true; const formFields = form.elements; const formData = new FormData(form); @@ -215,20 +214,27 @@ } } + btnSubmit.setAttribute('disabled', true); + fetch('{{ url_for("ApiUpload") }}', { method: 'POST', body: formData }) - .then(res => res.json()) + .then(res => { + return res.json(); + }) .then(data => { console.log(data); - btnSubmit.disabled = false; + btnSubmit.removeAttribute('disabled'); alert(data.message); - window.location.href = "{{ url_for('Home') }}"; + if (data.status != "error") { + window.location.href = "{{ url_for('Home') }}"; + } }) .catch(err => { console.log(err); - btnSubmit.disabled = false; + btnSubmit.removeAttribute('disabled'); + alert(err.message); }) });