TechnoSamurai02's picture
Add TruthShield AI MVP
c438edd
Raw
History Blame Contribute Delete
2.29 kB
from __future__ import annotations
import os
import tempfile
from pathlib import Path
from typing import Iterable
from fastapi import HTTPException, UploadFile
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp"}
VIDEO_EXTENSIONS = {".mp4", ".mov", ".webm"}
MAX_IMAGE_BYTES = 15 * 1024 * 1024
MAX_VIDEO_BYTES = 80 * 1024 * 1024
def safe_filename(filename: str | None) -> str:
if not filename:
return "upload"
return os.path.basename(filename)
def validate_extension(filename: str | None, allowed_extensions: Iterable[str]) -> str:
name = safe_filename(filename)
suffix = Path(name).suffix.lower()
if suffix not in set(allowed_extensions):
allowed = ", ".join(sorted(allowed_extensions))
raise HTTPException(status_code=400, detail=f"Unsupported file type. Allowed: {allowed}")
return suffix
async def read_upload_bytes(upload: UploadFile, max_bytes: int) -> bytes:
data = bytearray()
while True:
chunk = await upload.read(1024 * 1024)
if not chunk:
break
data.extend(chunk)
if len(data) > max_bytes:
raise HTTPException(status_code=413, detail="File is too large for this MVP analyzer.")
if not data:
raise HTTPException(status_code=400, detail="The uploaded file was empty.")
return bytes(data)
async def save_upload_to_temp_file(upload: UploadFile, suffix: str, max_bytes: int) -> str:
temp = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
path = temp.name
size = 0
try:
while True:
chunk = await upload.read(1024 * 1024)
if not chunk:
break
size += len(chunk)
if size > max_bytes:
raise HTTPException(status_code=413, detail="File is too large for this MVP analyzer.")
temp.write(chunk)
if size == 0:
raise HTTPException(status_code=400, detail="The uploaded file was empty.")
return path
except Exception:
try:
os.unlink(path)
except OSError:
pass
raise
finally:
temp.close()
def remove_temp_file(path: str | None) -> None:
if not path:
return
try:
os.unlink(path)
except OSError:
pass