Added local-file-system storage

This commit is contained in:
Mawoka
2022-04-01 22:25:09 +02:00
parent 918d778db0
commit 0ec7c2b519
8 changed files with 76 additions and 15 deletions
+5 -2
View File
@@ -26,8 +26,11 @@ class Settings(BaseSettings):
# storage_backend
storage_backend: str | None = "deta"
# if storage_backend == "deta":
deta_project_key: str
deta_project_id: str
deta_project_key: str | None
deta_project_id: str | None
# if storage_backend == "local":
storage_path: str | None
class Config:
env_file = ".env"
+1 -1
View File
@@ -66,7 +66,7 @@ async def import_quiz(quiz_id: str, user: User) -> Quiz | str:
quiz_questions: list[dict] = []
quiz_id = uuid.uuid4()
storage = Storage(backend=settings.storage_backend, deta_key=settings.deta_project_key,
deta_id=settings.deta_project_id)
deta_id=settings.deta_project_id, storage_path=settings.storage_path)
for q in quiz.kahoot.questions:
answers: list[QuizAnswer] = []
+7 -3
View File
@@ -1,19 +1,23 @@
from fastapi import APIRouter
from fastapi import APIRouter, HTTPException
from fastapi.responses import StreamingResponse
from classquiz.config import settings
import io
import re
from classquiz.storage import Storage
settings = settings()
router = APIRouter()
file_regex = r"^[a-z0-9]{8}-[a-z0-9-]{27}--[a-z0-9-]{36}$"
@router.get('/download/{file_name}')
async def download_file(file_name: str):
storage = Storage(backend=settings.storage_backend, deta_key=settings.deta_project_key,
deta_id=settings.deta_project_id)
deta_id=settings.deta_project_id, storage_path=settings.storage_path)
download = await storage.download(file_name)
if not re.match(file_regex, file_name):
raise HTTPException(status_code=400, detail="Invalid file name")
def iter_file():
yield from download
+10 -1
View File
@@ -1,17 +1,22 @@
from .deta_storage import DetaStorage
from .local_storage import LocalStorage
from io import BytesIO
class Storage:
def __init__(self, backend: str, deta_key: str | None, deta_id: str | None):
def __init__(self, backend: str, deta_key: str | None, deta_id: str | None, storage_path: str | None):
self.backend = backend
self.deta_key = deta_key
self.deta_id = deta_id
self.deta_base_url = f"https://drive.deta.sh/v1/{deta_id}/classquiz"
self.deta_instance = DetaStorage(deta_base_url=self.deta_base_url, deta_key=self.deta_key, deta_id=self.deta_id)
self.local_instance = LocalStorage(base_path=storage_path)
if backend == "deta":
if deta_key is None or deta_id is None:
raise ValueError("deta_key and deta_id must be provided")
if backend == "local":
if storage_path is None:
raise ValueError("storage_path must be provided")
else:
raise NotImplementedError(f"Backend {backend} not implemented")
@@ -19,7 +24,11 @@ class Storage:
if self.backend == "deta":
return await self.deta_instance.download(
file_name)
elif self.backend == "local":
return await self.local_instance.get_file(file_name)
async def upload(self, file_name: str, file_data: bytes) -> None:
if self.backend == "deta":
return await self.deta_instance.upload(file=file_data, file_name=file_name)
elif self.backend == "local":
return await self.local_instance.write_file(file_name=file_name, data=file_data)
+17
View File
@@ -0,0 +1,17 @@
import io
import os
import aiofiles
class LocalStorage:
def __init__(self, base_path: str):
self.base_path = base_path
async def get_file(self, file_name: str) -> io.BytesIO:
async with aiofiles.open(file=os.path.join(self.base_path, file_name), mode='rb') as f:
return io.BytesIO(await f.read())
async def write_file(self, file_name: str, data: bytes) -> None:
async with aiofiles.open(file=os.path.join(self.base_path, file_name), mode='wb') as f:
await f.write(data)