upload images

This commit is contained in:
Philip Cheung 2024-10-08 00:23:12 +08:00
parent 9214764484
commit 31ebaea838
13 changed files with 92 additions and 36 deletions

4
.env
View File

@ -1,9 +1,9 @@
# Domain # Domain
# This would be set to the production domain with an env var on deployment # This would be set to the production domain with an env var on deployment
DOMAIN=philip-cat.com DOMAIN=localhost
# Environment: local, staging, production # Environment: local, staging, production
ENVIRONMENT=staging ENVIRONMENT=local
PROJECT_NAME="All & One" PROJECT_NAME="All & One"
STACK_NAME=allandonecms STACK_NAME=allandonecms

View File

@ -32,7 +32,7 @@ async def create_aboutUs(
Create new about us. Create new about us.
""" """
validate_file_size_type(image) validate_file_size_type(image)
imageUrl = await save_picture(file=image, folderName="tmp") imageUrl = await save_picture(file=image, folder_name="tmp")
# aboutus_in.image = imageUrl # aboutus_in.image = imageUrl
aboutUs_in = AboutUsCreate(description=description, image=imageUrl, index=index ,title=title) aboutUs_in = AboutUsCreate(description=description, image=imageUrl, index=index ,title=title)
aboutUs = AboutUs.from_orm(aboutUs_in) aboutUs = AboutUs.from_orm(aboutUs_in)
@ -57,7 +57,7 @@ async def edit_aboutUs(
if image is not None: if image is not None:
validate_file_size_type(image) validate_file_size_type(image)
imageUrl = await save_picture(file=image, folderName="tmp") imageUrl = await save_picture(file=image, folder_name="tmp")
await del_picture(aboutUs.image) await del_picture(aboutUs.image)
aboutUs_in = AboutsUpdate(description=description, image=imageUrl, index=index, title=title) aboutUs_in = AboutsUpdate(description=description, image=imageUrl, index=index, title=title)
else : else :

View File

@ -26,7 +26,7 @@ async def create_image(
Create new image. Create new image.
""" """
validate_file_size_type(image) validate_file_size_type(image)
imageUrl = await save_picture(file=image, folderName="tmp") imageUrl = await save_picture(file=image, folder_name="tmp")
image_in = ImageCreate(image=imageUrl, index=index, course_id=course_id) image_in = ImageCreate(image=imageUrl, index=index, course_id=course_id)
image = Image.from_orm(image_in) image = Image.from_orm(image_in)
session.add(image) session.add(image)

View File

@ -26,7 +26,7 @@ async def create_info_image(
Create new image. Create new image.
""" """
validate_file_size_type(image) validate_file_size_type(image)
imageUrl = await save_picture(file=image, folderName="tmp") imageUrl = await save_picture(file=image, folder_name="tmp")
info_image_in = Info_ImageCreate(image=imageUrl, index=index, course_id=course_id) info_image_in = Info_ImageCreate(image=imageUrl, index=index, course_id=course_id)
info_image = Info_Image.from_orm(info_image_in) info_image = Info_Image.from_orm(info_image_in)
session.add(info_image) session.add(info_image)

View File

@ -7,6 +7,7 @@ from datetime import datetime, timedelta, timezone
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from uuid import uuid4 from uuid import uuid4
from botocore.exceptions import ClientError
from PIL import Image, ImageTk from PIL import Image, ImageTk
import emails # type: ignore import emails # type: ignore
import jwt import jwt
@ -15,7 +16,9 @@ from jwt.exceptions import InvalidTokenError
import filetype import filetype
from app.core.config import settings from app.core.config import settings
static = 'static' static = "static"
@dataclass @dataclass
class EmailData: class EmailData:
html_content: str html_content: str
@ -120,6 +123,7 @@ def verify_password_reset_token(token: str) -> str | None:
except InvalidTokenError: except InvalidTokenError:
return None return None
from fastapi import HTTPException, status from fastapi import HTTPException, status
from typing import IO from typing import IO
import filetype import filetype
@ -128,8 +132,19 @@ import filetype
def validate_file_size_type(file: IO): def validate_file_size_type(file: IO):
FILE_SIZE = 5097152 # 2MB FILE_SIZE = 5097152 # 2MB
accepted_file_types = ["image/png", "image/jpeg", "image/jpg", "image/heic", "image/heif", "image/heics", "png", accepted_file_types = [
"jpeg", "jpg", "heic", "heif", "heics" "image/png",
"image/jpeg",
"image/jpg",
"image/heic",
"image/heif",
"image/heics",
"png",
"jpeg",
"jpg",
"heic",
"heif",
"heics",
] ]
file_info = filetype.guess(file.file) file_info = filetype.guess(file.file)
if file_info is None: if file_info is None:
@ -153,7 +168,10 @@ def validate_file_size_type(file: IO):
for chunk in file.file: for chunk in file.file:
real_file_size += len(chunk) real_file_size += len(chunk)
if real_file_size > FILE_SIZE: if real_file_size > FILE_SIZE:
raise HTTPException(status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="Too large") raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="Too large"
)
# async def save_picture(file, folderName: str = '', fileName: str = None): # async def save_picture(file, folderName: str = '', fileName: str = None):
# randon_uid = str(uuid4()) # randon_uid = str(uuid4())
@ -175,11 +193,29 @@ def validate_file_size_type(file: IO):
# return f'{static}/{folderName}/{picture_name}' # return f'{static}/{folderName}/{picture_name}'
async def save_picture(file, folderName: str = "", fileName: str = None):
random_uid = str(uuid4())
_, f_ext = os.path.splitext(file.filename)
picture_name = (fileName.lower().replace(" ", "") if fileName else random_uid) + f_ext
async def upload_file(file_name, bucket_name, object_name=None):
ConnectionUrl = f"https://{settings.AccountID}.r2.cloudflarestorage.com"
r2 = boto3.client(
"s3",
endpoint_url=ConnectionUrl,
aws_access_key_id=settings.access_key_id,
aws_secret_access_key=settings.secret_access_key,
)
if object_name is None:
object_name = file_name
try:
r2.upload_file(file_name, bucket_name, object_name)
except ClientError as e:
print(f"An error occurred: {e}")
return False
return True
async def save_picture(file, folder_name: str = "", file_name: str = None):
import io
r2 = boto3.client( r2 = boto3.client(
"s3", "s3",
@ -188,21 +224,42 @@ async def save_picture(file, folderName: str = "", fileName: str = None):
aws_secret_access_key=settings.secret_access_key, aws_secret_access_key=settings.secret_access_key,
) )
randon_uid = str(uuid4())
_, f_ext = os.path.splitext(file.filename)
picture_name = (
randon_uid if file_name is None else file_name.lower().replace(" ", "")
) + f_ext
path = os.path.join(static, folder_name)
if not os.path.exists(path):
os.makedirs(path)
picture_path = os.path.join(path, picture_name)
# output_size = (125,125)
img = Image.open(file.file) img = Image.open(file.file)
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
r2.put_object(Bucket=settings.bucket_name, Key=f"{folderName}/{picture_name}", Body=img_byte_arr) # img.thumbnail(output_size)
img.save(picture_path)
r2_url = f"https://{settings.AccountID}.r2.cloudflarestorage.com/{settings.bucket_name}/{folderName}/{picture_name}" ConnectionUrl = f"https://{settings.AccountID}.r2.cloudflarestorage.com"
return r2_url S3Connect = boto3.client(
"s3",
endpoint_url=ConnectionUrl,
aws_access_key_id=settings.access_key_id,
aws_secret_access_key=settings.secret_access_key,
)
if upload_file(picture_path, "images"):
print(f"File {picture_path} uploaded successfully to images")
else:
print(f"File upload failed")
return f"{static}/{folder_name}/{picture_name}"
async def del_picture(picture_path): async def del_picture(picture_path):
try: try:
os.remove(picture_path) os.remove(picture_path)
except Exception as e: except Exception as e:
print('Error: ', e) print("Error: ", e)
return False return False
return True return True

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

@ -1 +1 @@
VITE_API_URL=https://localhost VITE_API_URL=http://localhost

View File

@ -80,8 +80,7 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => {
return substring return substring
}) })
let url = config.BASE + path const url = config.BASE + path
url = url.replace(/^http:\/\//i, 'https://')
return options.query ? url + getQueryString(options.query) : url return options.query ? url + getQueryString(options.query) : url
} }