import os import io import uvicorn from pathlib import Path from fastapi import FastAPI, Header from fastapi.responses import StreamingResponse from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from config import ServerConfig app = FastAPI() app.mount('/home', StaticFiles(directory="static", html=True), name="static") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"] ) @app.get("/fetch/{id}") async def fetch_file(id: str, range: str = Header(None)) -> StreamingResponse: video_path: Path = Path(os.path.join(ServerConfig.video_play_path, id + '.mp4')) video_size: int = video_path.stat().st_size start = 0 end = video_size - 1 chunk_size = min(video_size, ServerConfig.video_chunk_size) headers = { 'Content-Type': 'video/mp4', 'Content-Disposition': f'attachment; filename="{id}.mp4"', } if range: start, end = range.replace('bytes=', '').split('-') start = int(start) end = int(end) if end else video_size - 1 chunk_size: int = min(end - start + 1, ServerConfig.video_chunk_size) headers['Content-Range'] = f'bytes {start}-{end}/{video_size}' headers['Accept-Ranges'] = 'bytes' headers['Content-Disposition'] = 'inline' def file_reader(): with open(video_path, 'rb') as video: video.seek(start) while True: data = video.read(chunk_size) if not data: break yield data return StreamingResponse(file_reader(), status_code=206, headers=headers, media_type='video/mp4') if __name__ == "__main__": uvicorn.run(app=app)