影像从心:一张照片站的前后端 all-in-one
影像从心 是一个照片分享站:前台展示摄影作品,照片可以按分类筛选、在世界地图上按拍摄地点落点;后台支持登录、上传、编辑与删除。整个后端是一个 600 行左右的 Python 标准库单文件服务。
💡 一句话定位: 「一个 Python 文件就是整个后端」,复杂度全部花在体验上——地图落点、离线可用,而不是框架选型。
- 展示层 — 原生 HTML/CSS/JS + Leaflet 地图 · 作品瀑布流与分类筛选、高德底图瓦片 + 标准国界 china.geojson 落点、PWA 可安装
- 服务层 — Python 3.11 标准库单文件 · ThreadingHTTPServer 多线程、REST JSON API(列表/上传/编辑/删除/登录)、multipart 手动解析与类型校验
- 数据层 — 零数据库 · JSON 文件存照片索引(写操作加线程锁),uploads/ 目录存原图与缩略图,备份就是拷目录
- 离线层 — Service Worker · HTML 网络优先、静态资源缓存优先、地图瓦片独立缓存(上限 600 张)+ 上限淘汰
技术栈清单#
| 层 | 选型 | 说明 |
|---|---|---|
| 后端 | Python 3.11 标准库 ThreadingHTTPServer | 零第三方依赖,单文件 server.py |
| API | REST 风格 JSON 接口 | 照片列表 / 上传 / 删除 / 编辑 / 登录校验 |
| 存储 | JSON 元数据 + 文件系统 | data/ 存索引,uploads/ 存原图与缩略图 |
| 地图 | Leaflet + 高德底图瓦片 | 叠加中国标准国界 china.geojson 勾勒边界 |
| 离线 | Service Worker (PWA) | HTML 网络优先,静态资源缓存优先,瓦片独立缓存 |
| 网关 | nginx | TLS 终结、静态资源 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 缓存策略#
HTML 页面 → 永远走网络(保证内容最新)
/api /uploads → 网络优先,失败回退缓存
自有静态资源 → 缓存优先,回源后写入
高德瓦片 → 独立瓦片缓存 + 上限淘汰 (600 张)预缓存清单只放体积可控的关键资源(manifest、图标、leaflet、国界数据、封面图),每次改动静态资源必须递增 CACHE_NAME,否则老用户会一直命中旧缓存——这是 PWA 最常见的坑。
为什么不用 Flask / Django?需求就是「一张地图 + 一组照片 + 一个后台」,标准库
http.server 足够,换来的是:无依赖安装、无版本升级、systemd 拉起即跑。复杂度应该花在体验(地图、离线)而不是框架上。API 一览#
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