You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.7 KiB
Python
94 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
from pathlib import Path
|
|
|
|
from fastapi import APIRouter, Depends, File, Request, UploadFile
|
|
from sqlalchemy.orm import Session
|
|
|
|
from iti.auth import require_user
|
|
from iti.db import get_db
|
|
from iti.responses import ok
|
|
from iti.storage import StorageManager
|
|
|
|
from iti_system.models import SysFile
|
|
from iti_system.services import dump_file, new_id
|
|
|
|
|
|
router = APIRouter(prefix="/upload", tags=["common.upload"])
|
|
|
|
|
|
@router.post("", dependencies=[Depends(require_user)])
|
|
def upload_file(
|
|
request: Request,
|
|
file: UploadFile = File(...),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
file_id = new_id()
|
|
suffix = Path(file.filename or "").suffix
|
|
key = f"{file_id}{suffix}"
|
|
content = file.file.read()
|
|
storage = StorageManager.get_storage(
|
|
config=request.app.state.config.file_storage,
|
|
base_dir=request.app.state.config.base_dir,
|
|
)
|
|
storage_info = storage.upload(_BytesReader(content), key, file.content_type)
|
|
item = SysFile(
|
|
id=file_id,
|
|
filename=file.filename or key,
|
|
file_key=key,
|
|
file_hash=hashlib.sha256(content).hexdigest(),
|
|
mime_type=file.content_type,
|
|
file_size=len(content),
|
|
extension=suffix.lstrip(".") or None,
|
|
storage_type=storage.storage_type,
|
|
storage_info=storage_info,
|
|
)
|
|
db.add(item)
|
|
db.commit()
|
|
db.refresh(item)
|
|
return ok(dump_file(item))
|
|
|
|
|
|
@router.post("/chunk/init", dependencies=[Depends(require_user)])
|
|
def init_chunk_upload(filename: str):
|
|
return ok({"uploadId": new_id(), "filename": filename})
|
|
|
|
|
|
@router.post("/chunk/upload", dependencies=[Depends(require_user)])
|
|
def upload_chunk(upload_id: str, chunk_index: int):
|
|
return ok({"uploadId": upload_id, "chunkIndex": chunk_index})
|
|
|
|
|
|
@router.post("/chunk/merge", dependencies=[Depends(require_user)])
|
|
def merge_chunk(upload_id: str):
|
|
return ok({"uploadId": upload_id, "status": "merged"})
|
|
|
|
|
|
@router.delete("/chunk/{upload_id}", dependencies=[Depends(require_user)])
|
|
def cancel_chunk(upload_id: str):
|
|
return ok({"uploadId": upload_id})
|
|
|
|
|
|
@router.get("/chunk/{upload_id}/progress", dependencies=[Depends(require_user)])
|
|
def chunk_progress(upload_id: str):
|
|
return ok({"uploadId": upload_id, "uploadedChunks": []})
|
|
|
|
|
|
@router.post("/chunk/cleanup", dependencies=[Depends(require_user)])
|
|
def cleanup_chunk(days: int = 7):
|
|
return ok({"days": days})
|
|
|
|
|
|
class _BytesReader:
|
|
def __init__(self, value: bytes) -> None:
|
|
self._value = value
|
|
self._offset = 0
|
|
|
|
def read(self, size: int = -1) -> bytes:
|
|
if size is None or size < 0:
|
|
size = len(self._value) - self._offset
|
|
chunk = self._value[self._offset : self._offset + size]
|
|
self._offset += len(chunk)
|
|
return chunk
|