--- last_reviewed: 2026-10-19 --- # src/upload — 扫码上传收件器 **独立进程**,不是 MCP 工具,也绝不由 MCP 子进程拉起(生命周期要独立于宿主,重启宿主不能带走上传口)。 ```bash uv run python -m src.upload.server # 0.0.0.0:5055 uv run python -m src.upload.server --local # 只监听 127.0.0.1 uv run python -m src.upload.server --port 6000 --pin 1234 ``` | 文件 | 职责 | |------|------| | `server.py` | Flask 应用与路由、上限与白名单、`lan_ip()`、命令行参数 | | `page.py` | 页面模板(内联 CSS,零外部 CDN,`__PLACEHOLDER__` 占位替换) | ## 路由 | 路由 | 说明 | |------|------| | `GET /` | PC 端首页(可选 PIN 校验) | | `GET /qr/` | 服务端生成的二维码 PNG(segno) | | `GET /u/` | 手机上传页(令牌在 URL 里) | | `POST /u/` | 接收文件,落 `cases//inbox/` | | `GET /api/inbox/` | 该会话待收数量(只给数量,不给内容) | ## 安全边界 - 默认 `0.0.0.0` 是刻意的(手机要用局域网 IP 访问),补偿控制如下 - **每会话令牌强制**:`case.json` 里的 `upload_token`,缺失或错误一律 403;工具输出里永不回显令牌明文, 只在 `case_create` 返回的页面地址中出现一次 - **只写不读**:没有文件列表、没有下载路由 - 扩展名白名单、单文件 25MB、每会话 200 个文件封顶 - 文件名一律 `Path(raw.replace(chr(92), '/')).name` 取基名 + 重名加序号,防目录穿越 - 可选 `--pin` / `UPLOAD_PIN` / `config.json` 的 `upload_pin` 作为额外访问码 `cases//inbox/` 里的文件由宿主调 `case_add_files(source='inbox')` 收取进会话,收件器本身不碰任何业务逻辑。