影像从心:一张照片站的前后端 all-in-one

影像站PythonLeafletPWAREST API
2026-10-11 · 980 字 · 约 3 分钟
本文目录(7 节)

影像从心 是一个照片分享站:前台展示摄影作品,照片可以按分类筛选、在世界地图上按拍摄地点落点;后台支持登录、上传、编辑与删除。整个后端是一个 600 行左右的 Python 标准库单文件服务。

💡 一句话定位: 「一个 Python 文件就是整个后端」,复杂度全部花在体验上——地图落点、离线可用,而不是框架选型。
  • 展示层 — 原生 HTML/CSS/JS + Leaflet 地图 · 作品瀑布流与分类筛选、高德底图瓦片 + 标准国界 china.geojson 落点、PWA 可安装
  • 服务层 — Python 3.11 标准库单文件 · ThreadingHTTPServer 多线程、REST JSON API(列表/上传/编辑/删除/登录)、multipart 手动解析与类型校验
  • 数据层 — 零数据库 · JSON 文件存照片索引(写操作加线程锁),uploads/ 目录存原图与缩略图,备份就是拷目录
  • 离线层 — Service Worker · HTML 网络优先、静态资源缓存优先、地图瓦片独立缓存(上限 600 张)+ 上限淘汰
图 1 · 影像站的技术组成(后端只有一个文件)
图 1 · 影像站的技术组成(后端只有一个文件)影像从心展示层原生 HTML/CSS/JSLeaflet 地图落点PWA 可安装服务层标准库单文件REST JSON APImultipart 上传解析密码头鉴权数据层JSON 元数据索引uploads 原图与缩略图Service Worker 缓存

技术栈清单#

层选型说明
后端Python 3.11 标准库 ThreadingHTTPServer零第三方依赖,单文件 server.py
APIREST 风格 JSON 接口照片列表 / 上传 / 删除 / 编辑 / 登录校验
存储JSON 元数据 + 文件系统data/ 存索引,uploads/ 存原图与缩略图
地图Leaflet + 高德底图瓦片叠加中国标准国界 china.geojson 勾勒边界
离线Service Worker (PWA)HTML 网络优先,静态资源缓存优先,瓦片独立缓存
网关nginxTLS 终结、静态资源 30 天强缓存、静态资产正则路由

几个关键设计#

1. 分层极简但有边界#

单个 server.py 里依然遵守「路由解析 → 数据操作 → 响应格式化」的分层,所有写操作走统一的 JSON 元数据落盘函数并加线程锁,ThreadingHTTPServer 多线程并发下不会写坏索引文件。

2. 管理鉴权:密码头 + 服务端校验#

  • 管理员密码只存服务端(支持 MEMORY_ADMIN_PASSWORD 环境变量覆盖);
  • 所有写接口要求 X-Admin-Password 头,服务端逐一校验;
  • 上传走 multipart/form-data,服务端手动解析边界并校验文件类型与大小。

3. 地图落点与合规边界#

照片按拍摄经纬度在 Leaflet 地图上打点,底图用高德瓦片。国界显示用了自托管的 china.geojson 标准国界数据并开启 force-cache,既保证绘制规范,也避免每次访问都重新拉取。

4. Service Worker 缓存策略#

text
HTML 页面      → 永远走网络(保证内容最新)
/api /uploads  → 网络优先,失败回退缓存
自有静态资源   → 缓存优先,回源后写入
高德瓦片       → 独立瓦片缓存 + 上限淘汰 (600 张)

预缓存清单只放体积可控的关键资源(manifest、图标、leaflet、国界数据、封面图),每次改动静态资源必须递增 CACHE_NAME,否则老用户会一直命中旧缓存——这是 PWA 最常见的坑。

为什么不用 Flask / Django?需求就是「一张地图 + 一组照片 + 一个后台」,标准库 http.server 足够,换来的是:无依赖安装、无版本升级、systemd 拉起即跑。复杂度应该花在体验(地图、离线)而不是框架上。

API 一览#

text
GET  /api/photos              照片列表 (?cat=&order=)
GET  /uploads/<file>          照片文件
POST /api/login               管理员登录校验
POST /api/upload              上传 (multipart)
POST /api/photo/<id>/delete   删除
POST /api/photo/<id>/update   编辑标题/分类/落点
POST /api/photos/batch-place  批量标注落点
🏷 Python🏷 Leaflet🏷 PWA🏷 REST API
💬 问我 只依据站内资料作答
可以问这个站点的技术内容,例如「pycamp 的代码沙箱怎么做的」「为什么不直接用向量检索」。