mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 18:05:03 +00:00
2.5 KiB
2.5 KiB
Design
Роут в web/app.py
После /bundle/... (в конце файла) добавить:
from fastapi.responses import FileResponse
MEDIA_DIRS = [
BASE_DIR / "media", # свежие: media/<file>
BASE_DIR / "media" / "media" # старые: media/media/<file>
]
@app.get("/media/{filename}")
def media(request: Request, filename: str):
"""Отдаёт медиа-файл поста (из media/ или media/media/). Авторизация."""
_require_auth(request)
name = os.path.basename(filename) # защита от path traversal
if not name:
return HTMLResponse("bad filename", status_code=400)
for d in MEDIA_DIRS:
f = (d / name).resolve()
if f.exists() and f.is_file():
# отдаём с корректным MIME по расширению
return FileResponse(f)
return HTMLResponse("not found", status_code=404)
Примечание: FileResponse уже есть в fastapi.responses (импортировать).
MEDIA_DIRS можно вынести в константы рядом с STATIC_DIR.
Шаблоны
В candidates.html (и published.html), заменить блок бейджа:
{% if p.media_path %}
<span class="badge bg-light text-dark ms-2">🖼 медиа</span>
{# маленькое превью: изображение или видео #}
{% set media_src = '/media/' ~ p.media_path.split('/')[-1] %}
{% if p.media_path.lower().endswith(('.jpg','.jpeg','.png','.gif','.webp')) %}
<img src="{{ media_src }}" class="img-fluid rounded mt-2" style="max-height:180px" alt="медиа">
{% elif p.media_path.lower().endswith(('.mp4','.webm','.mov')) %}
<video src="{{ media_src }}" controls class="mt-2" style="max-height:180px"></video>
{% endif %}
{% endif %}
В candidates.html строка 49: заменить бейдж на блок с превью.
В published.html — аналогично (там сейчас бейдж медиа? проверить).
Верификация
openspec validate web-media-preview— чисто.- Перезапуск веба:
sudo systemctl restart vesti-web. - Открыть /candidates — у поста с media_path видно изображение/видео.
/media/LinuxMastery_1079.jpg— 200 (файл есть).- Старый пост с media/media/ — тоже 200.
- Несуществующий файл — 404.