diff --git a/app/routers/ui.py b/app/routers/ui.py index b325139..d8ae935 100644 --- a/app/routers/ui.py +++ b/app/routers/ui.py @@ -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 diff --git a/app/templates/job_detail.html b/app/templates/job_detail.html index 3ea8280..177efa2 100644 --- a/app/templates/job_detail.html +++ b/app/templates/job_detail.html @@ -98,12 +98,19 @@
File & Geometry - {% if job.file_name and not job.file_name.endswith('.gcode') %} -
- -
+ {% if job.file_name %} +
+ + Download + + {% if not job.file_name.endswith('.gcode') %} +
+ +
+ {% endif %} +
{% endif %}
@@ -350,6 +357,13 @@