Refine seller store implementation
This commit is contained in:
@@ -54,22 +54,25 @@
|
||||
- 已实施:页面独立轮询水印任务,刷新可恢复,支持取消、重试全部失败项和按单张重试;等待期间素材被修改时会拒绝旧任务覆盖,单项重试会重新冻结最新版本。
|
||||
- 边界:移除水印目前仍是同步短操作;若未来单次处理规模继续提高,可迁入同一 Worker 框架。
|
||||
|
||||
### P2:统一图片格式、尺寸和元数据校验
|
||||
### P2:统一图片格式、尺寸和元数据校验(已实施)
|
||||
|
||||
- 现状:存储层主要依据 URL 后缀或 Content-Type 推断格式,未统一校验文件大小、像素、实际 MIME 类型和方向信息。
|
||||
- 涉及:`server/services/storage.py`、`server/api/materials.py`。
|
||||
- 建议:上传/下载后用图片库校验真实格式,限制像素与文件大小,按需要压缩、纠正 EXIF 方向并记录宽高。
|
||||
- 已实施:`normalize_image_bytes()` 在上传、采集转存和 AI 生成图写入素材库时,使用 Pillow 解码真实字节,不再信任 URL 后缀或客户端 Content-Type;仅接受 JPEG、PNG、WebP、GIF、BMP。
|
||||
- 已实施:维持原有单文件字节上限,并新增 `IMAGE_MAX_PIXELS`(默认 40,000,000)限制;强制完整解码,拒绝损坏、伪造或像素过大的图片。
|
||||
- 已实施:静态图纠正 EXIF 方向;记录可信的实际宽高到 `product_assets.width`、`height`。动画图只校验并保留原字节,不重编码以避免丢帧。
|
||||
- 已实施:历史本地库的 39 条图片素材已通过 `server/scripts/backfill_asset_dimensions.py` 回填宽高;该脚本不重写图片文件,可用于其他旧库。
|
||||
- 边界:当前不做强制压缩/转码,避免无谓损失采集原图质量;后续若存储成本成为问题,再按真实运营数据引入按格式和尺寸分级压缩策略。
|
||||
|
||||
---
|
||||
|
||||
## 3. 服务端:安全与资源保护
|
||||
|
||||
### P0:限制图片代理和导出 URL,防止 SSRF
|
||||
### P0:限制图片代理和导出 URL,防止 SSRF(已实施)
|
||||
|
||||
- 现状:图片代理、单图下载、ZIP 导出会请求客户端传入的 HTTP(S) URL,并跟随重定向。
|
||||
- 涉及:`server/api/proxy.py`、`server/api/export.py`、`server/services/storage.py`。
|
||||
- 风险:若服务可被非本机访问,可能被用于读取内网地址、云元数据地址,或下载超大文件。
|
||||
- 建议:解析并拒绝回环、内网、链路本地与保留 IP;每次重定向后再次校验;设置域名白名单/允许列表、最大响应体、连接与总耗时上限。
|
||||
- 已实施:`services.storage.download_bytes()` 统一校验代理、采集转存、AI 参考图和远程导出的 URL,仅允许公网 `http(s)` 地址;拒绝 `localhost`、回环、内网、链路本地、多播及其他保留 IP。
|
||||
- 已实施:关闭 HTTP 客户端自动重定向,最多手动跟随 3 跳,并在每一跳重新解析和校验目标地址;限制连接、读写和整次下载总耗时。原有的流式大小上限继续生效。
|
||||
- 兼容:项目自身已经转存的 `/media/...` 素材仍通过受限本地文件读取;采集扩展的 `GET /api/proxy-image?url=https://公网源图` 防盗链回退不受影响。
|
||||
- 涉及:`server/api/proxy.py`、`server/api/export.py`、`server/services/storage.py`、`.env.example`。
|
||||
- 边界:当前策略按 DNS 解析结果判定公网地址;若未来服务面向高风险公网环境,可进一步使用出站网络策略或固定 DNS/代理以降低 DNS 重绑定窗口。
|
||||
|
||||
### P0:限制上传与 ZIP 导出的内存占用(已实施基础版本)
|
||||
|
||||
@@ -89,16 +92,17 @@
|
||||
|
||||
## 4. 前端:可维护性与交互
|
||||
|
||||
### P2:拆分 TrialSuitePanel
|
||||
### P2:拆分 TrialSuitePanel(已实施)
|
||||
|
||||
- 现状:`TrialSuitePanel.tsx` 已约 1,400 行,采集图和生成图卡片、悬浮操作、选择、下载等逻辑有重复。
|
||||
- 建议:拆分为素材网格、结果网格、图片动作层、预览下载、水印设置、套图轮询等子组件/hooks。
|
||||
- 收益:降低后续 UI 修改遗漏风险,便于复用和测试。
|
||||
- 已实施:`TrialSuitePanel.tsx` 从约 1,829 行缩减为约 1,326 行;采集素材网格、生成结果网格、失败结果卡片提取到 `TrialImageGrids.tsx`,水印设置和水印任务状态提取到 `TrialWatermarkSettings.tsx`,图片分组、预览和结果类型统一到 `trialImageTypes.ts`。
|
||||
- 已实施:采集图与生成图统一复用卡片的选择、删除、下载、AI 编辑和预览行为,避免两处网格逻辑继续分叉。
|
||||
- 边界:套图和水印轮询保留在父组件,继续集中管理页面级状态、刷新与取消逻辑;若轮询逻辑再次扩张,再独立为 hook。
|
||||
|
||||
### P2:图片多时采用懒加载/虚拟化
|
||||
### P2:图片多时采用懒加载/虚拟化(已实施基础版本)
|
||||
|
||||
- 现状:图片网格会一次性创建全部 Ant Design Image 与预览节点。
|
||||
- 建议:大量历史生成图时采用分页、虚拟列表或按需加载;缩略图使用合适尺寸和 `loading="lazy"`。
|
||||
- 已实施:采集素材按分组、套图结果和历史生成记录均按每页 24 张分页;仅当前页创建 Ant Design `Image` 及预览节点,避免历史图片一次性进入 DOM。
|
||||
- 已实施:缩略图使用 `loading="lazy"`,滚动接近可视区才请求图片资源。
|
||||
- 边界:当前采用分页而非滚动虚拟列表,预览导航限于当前页;若单个分组进一步增长到数百张以上,可基于真实使用情况再替换为虚拟网格或服务端游标分页。
|
||||
|
||||
### P2:补触屏与键盘操作
|
||||
|
||||
|
||||
Reference in New Issue
Block a user