Initial commit

This commit is contained in:
shahzeydyfah
2024-02-15 00:17:51 +03:30
commit 4b0396466d
111 changed files with 6296 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
from .urls import *
+1
View File
@@ -0,0 +1 @@
from .upload import *
+18
View File
@@ -0,0 +1,18 @@
import uuid
from typing import Optional, Union, Any
from pydantic import Field
from core.models.base import BaseModel, BaseCUAt
class FileModel(BaseModel, BaseCUAt):
id: Union[Optional[uuid.UUID], str] = Field(alias='_id')
owner_id: Optional[Union[uuid.UUID, str]]
module: Optional[str]
payload: Optional[Any]
file_name: str
file_type: str
file_size: int
storage: str
driver: Optional[str]
+100
View File
@@ -0,0 +1,100 @@
import hashlib
import json
import os
import uuid
from datetime import date
from pathlib import Path
import aiofiles
from PIL import Image
from fastapi import UploadFile, HTTPException
from starlette.responses import FileResponse
from core.utils import is_valid_uuid
from core.service.mongo_db import use_collection
from root import ROOT_DIR
from upload.models.upload import FileModel
COLLECTION = 'files'
ThisModel = FileModel
def create_dir(path: str) -> None:
"""Create a directory if it does not exist."""
if not os.path.exists(path):
os.makedirs(path)
def _fix_str_uuid(data: dict) -> dict:
for key, value in data.items():
if isinstance(value, str) and is_valid_uuid(value):
data[key] = uuid.UUID(value)
return data
def storage_path(dest: str = '', prefix='storage/') -> Path:
return Path(__file__).parent.parent.parent.joinpath(f'{prefix}{dest}')
class UploadRepository:
@staticmethod
async def upload(file: UploadFile, data: str, module):
if data:
data = json.JSONDecoder().decode(data)
if isinstance(data, dict):
data = _fix_str_uuid(data)
content = await file.read() # async read
file_size = len(content)
ext = file.filename.split('.')[-1]
file_name = '{0}.{1}'.format(hashlib.md5(content).hexdigest(), ext)
today = date.today()
dir = Path(__file__).parent.parent.parent.joinpath(
'storage/' + today.strftime("%Y%m"))
create_dir(dir.__str__())
path = dir.joinpath(file_name)
async with aiofiles.open(path, 'wb') as out_file:
await out_file.write(content) # async write
if file.content_type.startswith('image'):
UploadRepository._generate_thumbnail(dir, file_name)
UploadRepository._generate_thumbnail(dir, file_name, (512, 512))
UploadRepository._generate_thumbnail(dir, file_name, (48, 48))
model = ThisModel(
file_name=file.filename,
file_type=file.content_type,
file_size=file_size / 1024,
module=module,
payload=data,
storage=path.relative_to(ROOT_DIR).as_posix().__str__(),
).init_id().cu_at()
result = await use_collection(COLLECTION).insert_one(model.mongo_dict())
assert result.acknowledged
return model.mongo_dict()
@staticmethod
def _generate_thumbnail(dir: Path, file_name, size=(256, 256)):
try:
im = Image.open(dir.joinpath(file_name))
im.thumbnail(size)
thumb_dir = dir.joinpath('thumb').__str__()
create_dir(thumb_dir)
thumb_name = '{0}_{1}'.format(str(size[0]), file_name)
im.save('{0}/{1}'.format(thumb_dir, thumb_name, "JPEG"))
except IOError:
print("cannot create thumbnail for")
@staticmethod
async def get_file(_id: uuid.UUID):
result = await use_collection(COLLECTION).find_one({"_id": _id})
if not result:
raise HTTPException(status_code=404, detail='File Not Found')
file = storage_path(result.get('storage'), '')
return FileResponse(file)
+1
View File
@@ -0,0 +1 @@
from .upload import *
+29
View File
@@ -0,0 +1,29 @@
from typing import Any, Optional
from uuid import UUID
from fastapi import Body, UploadFile, File
from config import conf
from core.app import app
from core.utils.router import generate_router, safe_route
from upload.models import FileModel
from upload.repositories.upload import UploadRepository
router = generate_router("file", auth_dependencies=True, version='v2')
_tag_base = ['file']
_pre = conf.server.prefix_url.replace('v1', 'v2')
@router.post('/upload', response_model=FileModel, tags=_tag_base)
async def upload(file: UploadFile = File(...), payload: Optional[Any] = Body(None), module: Optional[str] = Body(None)):
return await safe_route('upload', UploadRepository.upload, file, payload, module)
@app.get(f'{_pre}' + '/file/{_id}', tags=_tag_base)
async def upload(_id: UUID):
return await UploadRepository.get_file(_id)
app.include_router(router)