Add file download for job models

- GET /files/{filename}: serves file from STL_UPLOAD_DIR with path-traversal guard
- Download button in File & Geometry card header (always visible when file attached)
- Download button also appears at the top of the Start Job modal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Martin Hohenberg
2026-06-18 22:52:26 +02:00
parent 51a7791461
commit bef57027f2
2 changed files with 33 additions and 7 deletions

View File

@@ -4,7 +4,7 @@ from datetime import datetime, timedelta
from pathlib import Path
from fastapi import APIRouter, Depends, File, Form, Request, UploadFile
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy import case, or_
from sqlalchemy.orm import Session
@@ -297,6 +297,18 @@ def edit_job(
return RedirectResponse(url=f"/jobs/{job_id}", status_code=HTTP_303_SEE_OTHER)
@router.get("/files/{filename}")
def download_file(filename: str):
from fastapi import HTTPException
stl_dir = get_stl_dir()
path = (stl_dir / filename).resolve()
if not str(path).startswith(str(stl_dir.resolve())):
raise HTTPException(400, "Invalid filename")
if not path.exists():
raise HTTPException(404, "File not found")
return FileResponse(path, filename=filename, media_type="application/octet-stream")
@router.post("/jobs/{job_id}/start")
def start_job(job_id: int, printer_id: int = Form(...), db: Session = Depends(get_db)):
from fastapi import HTTPException