crm/docs/screenshot-storage-comparison.md

5.8 KiB
Raw Blame History

截图存储方案对比

方案对比总览

特性 文件系统存储 数据库 Base64 存储
数据一致性 可能不一致 完全一致
备份恢复 需要分别备份 只需备份数据库
部署复杂度 需要配置文件服务 无需额外配置
多服务器部署 需要共享存储 无需共享存储
维护成本 需要清理孤立文件 自动管理
数据大小 原始大小 ⚠️ 增加 33%
查询性能 不影响 不影响LONGTEXT优化

架构对比

旧方案:文件系统存储

┌─────────────┐
│   前端      │
└──────┬──────┘
       │ 1. 上传图片
       ▼
┌─────────────────┐
│  后端 API       │
│  - 保存到文件   │──────┐
│  - 返回路径     │      │ 2. 写入文件
└──────┬──────────┘      ▼
       │              ┌──────────────┐
       │ 3. 保存路径  │ 文件系统     │
       ▼              │ /uploads/... │
┌─────────────────┐  └──────────────┘
│   数据库        │
│ screenshots:    │
│ ["/static/..."] │
└─────────────────┘

问题:
❌ 数据库和文件系统可能不一致
❌ 删除记录时文件可能残留
❌ 文件被删除但数据库仍有记录

新方案:数据库 Base64 存储

┌─────────────┐
│   前端      │
└──────┬──────┘
       │ 1. 上传图片
       ▼
┌─────────────────────┐
│  后端 API           │
│  - 转换为 Base64    │
│  - 返回 Data URL    │
└──────┬──────────────┘
       │ 2. 保存 Base64
       ▼
┌─────────────────────┐
│   数据库            │
│ screenshots:        │
│ ["data:image/..."]  │
└─────────────────────┘

优势:
✅ 数据完全一致
✅ 删除记录时图片自动删除
✅ 备份恢复只需处理数据库

数据流对比

上传流程

旧方案:

图片文件 → 保存到磁盘 → 生成路径 → 存入数据库
         (可能失败)   (返回前端)  (可能失败)

新方案:

图片文件 → 转换 Base64 → 存入数据库
                       (一次性完成)

读取流程

旧方案:

查询数据库 → 获取路径 → 配置静态服务 → 前端请求文件
          (可能不存在)  (需要配置)    (可能 404)

新方案:

查询数据库 → 获取 Base64 → 前端直接显示
          (一定存在)     (无需额外请求)

实际案例

问题场景(旧方案)

用户报告GET /static/uploads/screenshots/bd232714-58ac-472b-b3d0-18e7e768afe0.jpg 404

原因分析:
1. 数据库中有记录screenshots: ["/static/uploads/screenshots/bd232714..."]
2. 但文件系统中文件不存在
3. 可能原因:
   - 手动清理了上传目录
   - 服务器迁移时未同步文件
   - 磁盘故障导致文件丢失

解决方案(新方案)

数据库记录:
{
  "screenshots": [
    "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
  ]
}

特点:
✅ 图片数据直接在数据库中
✅ 查询到记录就一定能显示图片
✅ 不会出现 404 错误

性能影响分析

存储空间

原始图片: 1 MB
Base64 编码: 1.33 MB (+33%)

示例:
- 5 张截图,每张 500 KB
- 文件系统: 2.5 MB
- Base64: 3.3 MB (+0.8 MB)

数据库性能

-- LONGTEXT 字段不影响其他字段查询
SELECT id, customer_name, created_at
FROM customers;
-- ✅ 不会加载 screenshots 字段

-- 只有明确查询时才加载
SELECT screenshots
FROM customers
WHERE id = 'xxx';
-- ⚠️ 会加载完整的 Base64 数据

网络传输

旧方案:

1. API 请求: 返回路径 (~100 bytes)
2. 图片请求: 下载文件 (1 MB)
总计: 2 次请求

新方案:

1. API 请求: 返回 Base64 (1.33 MB)
总计: 1 次请求

最佳实践建议

适合使用 Base64 存储的场景

  • 截图、缩略图等小图片
  • 需要保证数据一致性
  • 简化部署和维护
  • 单张图片 < 2 MB
  • 每条记录图片数量 < 10 张

⚠️ 不适合的场景

  • 高清大图(> 5 MB
  • 大量图片(> 20 张/记录)
  • 需要图片处理(缩放、裁剪)
  • 需要 CDN 加速

💡 推荐方案

小图片(截图、头像): Base64 存储 ✅
大图片(产品图、相册): 对象存储OSS+ URL 引用

迁移检查清单

  • 数据库字段升级为 LONGTEXT
  • 上传接口返回 Base64 Data URL
  • 前端代码兼容两种格式
  • 测试上传功能
  • 测试显示功能
  • 验证数据库存储
  • 性能测试
  • 备份验证

总结

通过将截图存储从文件系统迁移到数据库 Base64 存储,我们:

  1. 彻底解决了数据一致性问题 - 这是最重要的改进
  2. 简化了部署和维护 - 无需管理文件系统
  3. 提高了系统可靠性 - 不会出现文件丢失的情况
  4. 付出了可接受的代价 - 存储空间增加 33%,但换来了更好的数据完整性

这是一个典型的用空间换可靠性的工程决策。