51 lines
No EOL
1.8 KiB
Python
51 lines
No EOL
1.8 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from motor.motor_asyncio import AsyncIOMotorDatabase
|
|
|
|
from ...core.database import get_database
|
|
from ...core.dependencies import get_current_user
|
|
from ...models.user import User
|
|
from ...schemas.file import SignedUploadRequest, SignedUploadResponse
|
|
from ...services.gcs import generate_signed_upload_url
|
|
|
|
router = APIRouter(prefix="/files", tags=["files"])
|
|
|
|
|
|
@router.post("/signed-upload", response_model=SignedUploadResponse)
|
|
async def get_signed_upload_url(
|
|
request: SignedUploadRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncIOMotorDatabase = Depends(get_database),
|
|
):
|
|
"""
|
|
Generate a signed URL for direct browser-to-GCS upload
|
|
This optimizes large file uploads by bypassing the API server
|
|
"""
|
|
if not request.content_type.startswith("video/"):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Only video files are supported"
|
|
)
|
|
|
|
# Generate unique blob path
|
|
from bson import ObjectId
|
|
blob_path = f"temp/{ObjectId()}/{request.filename}"
|
|
|
|
try:
|
|
# Generate signed upload URL with form fields
|
|
signed_data = await generate_signed_upload_url(
|
|
blob_path=blob_path,
|
|
content_type=request.content_type,
|
|
max_size=request.max_size or 1024 * 1024 * 1024 # 1GB default
|
|
)
|
|
|
|
return SignedUploadResponse(
|
|
upload_url=signed_data["url"],
|
|
fields=signed_data["fields"],
|
|
blob_path=blob_path
|
|
)
|
|
|
|
except Exception as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Failed to generate signed upload URL: {str(e)}"
|
|
) |