feat(upload): add directory traversal, queue throttling, and upload config settings
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -232,6 +232,22 @@ class Settings(BaseSettings):
|
||||
description="Delay in seconds between each task submission when throttling in /processall",
|
||||
)
|
||||
|
||||
# Client-side upload throttling settings (applied when uploading files via the web UI)
|
||||
upload_concurrency: int = Field(
|
||||
default=3,
|
||||
description=(
|
||||
"Maximum number of files uploaded simultaneously from the browser. "
|
||||
"Limits parallel uploads to prevent API overload when dragging directories. Default: 3."
|
||||
),
|
||||
)
|
||||
upload_queue_delay_ms: int = Field(
|
||||
default=500,
|
||||
description=(
|
||||
"Delay in milliseconds between starting each upload slot when queue is active. "
|
||||
"Staggers upload starts to smooth out server load. Default: 500 ms."
|
||||
),
|
||||
)
|
||||
|
||||
# Notification settings
|
||||
notification_urls: Union[List[str], str] = Field(
|
||||
default_factory=list,
|
||||
|
||||
@@ -1057,6 +1057,28 @@ SETTING_METADATA = {
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"upload_concurrency": {
|
||||
"category": "Processing",
|
||||
"description": (
|
||||
"Maximum number of files uploaded simultaneously from the browser. "
|
||||
"Limits parallel uploads to prevent API overload when dragging directories. Default: 3."
|
||||
),
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"upload_queue_delay_ms": {
|
||||
"category": "Processing",
|
||||
"description": (
|
||||
"Delay in milliseconds between starting each upload slot when queue is active. "
|
||||
"Staggers upload starts to smooth out server load. Default: 500 ms."
|
||||
),
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"enable_text_quality_check": {
|
||||
"category": "Processing",
|
||||
"description": (
|
||||
|
||||
@@ -17,6 +17,26 @@ router = APIRouter()
|
||||
_FILE_NOT_FOUND = "File not found"
|
||||
|
||||
|
||||
def _get_upload_concurrency() -> int:
|
||||
"""Return the configured upload concurrency (falls back to default on error)."""
|
||||
try:
|
||||
from app.config import settings
|
||||
|
||||
return settings.upload_concurrency
|
||||
except Exception:
|
||||
return 3
|
||||
|
||||
|
||||
def _get_upload_queue_delay_ms() -> int:
|
||||
"""Return the configured upload queue delay in ms (falls back to default on error)."""
|
||||
try:
|
||||
from app.config import settings
|
||||
|
||||
return settings.upload_queue_delay_ms
|
||||
except Exception:
|
||||
return 500
|
||||
|
||||
|
||||
@router.get("/files")
|
||||
@require_login
|
||||
def files_page(
|
||||
@@ -111,6 +131,8 @@ def files_page(
|
||||
"mime_type": mime_type or "",
|
||||
"status": status or "",
|
||||
"mime_types": mime_types,
|
||||
"upload_concurrency": _get_upload_concurrency(),
|
||||
"upload_queue_delay_ms": _get_upload_queue_delay_ms(),
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
@@ -124,6 +146,8 @@ def files_page(
|
||||
"files": [],
|
||||
"pagination": {"page": 1, "per_page": per_page, "total_items": 0, "total_pages": 0},
|
||||
"error": str(e),
|
||||
"upload_concurrency": _get_upload_concurrency(),
|
||||
"upload_queue_delay_ms": _get_upload_queue_delay_ms(),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
+10
-1
@@ -99,7 +99,16 @@ async def serve_imprint(request: Request):
|
||||
@require_login
|
||||
async def serve_upload(request: Request):
|
||||
"""Serve the upload page."""
|
||||
return templates.TemplateResponse("upload.html", {"request": request})
|
||||
from app.config import settings
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"upload.html",
|
||||
{
|
||||
"request": request,
|
||||
"upload_concurrency": settings.upload_concurrency,
|
||||
"upload_queue_delay_ms": settings.upload_queue_delay_ms,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/favicon.ico", include_in_schema=False)
|
||||
|
||||
Reference in New Issue
Block a user