Files
test-repo/docs/zh-cn/appendix/4-server-and-backend/file-storage.md
T
sanbuphy df51f84ab5 docs: 重构 README 附录展示 & 新增多个附录交互组件
README 更新:
- 移除顶部 header.png 横幅图片
- 新增「附录知识库」板块,以 3×3 网格展示 9 大知识领域精选内容
- 附录链接指向部署版网站 (datawhalechina.github.io)
- 阶段表格新增「附录」行,突出 80+ 交互式专题
- 章节标题「新手入门 & PM」简化为「零基础入门」
- News 新增 2026-02-25 附录知识库更新条目

新增交互组件:
- 异步任务队列 (async-task-queues) 演示组件
- 文件存储 (file-storage) 演示组件
- 项目架构 (project-architecture) 演示组件
- 限流与背压 (rate-limiting) 演示组件
- 搜索引擎 (search-engines) 演示组件
- 计算机基础: AppLaunch/BiosUefi/OSBoot 等启动流程演示组件

新增附录文档:
- 前端项目架构 (frontend-project-architecture.md)
- 后端项目架构 (backend-project-architecture.md)

内容优化:
- 算法思维、数据结构、编程语言、调试艺术等多篇附录内容更新
- HTML/CSS 布局、请求旅程等前后端文档完善
- 附录索引页 (index.md) 同步更新
2026-02-25 12:22:49 +08:00

163 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 文件存储与对象存储
::: tip 前言
**用户上传了一张头像,你把它存在服务器的 `/uploads` 目录下——然后服务器磁盘满了,或者你加了第二台服务器,用户发现头像时有时无。** 文件存储看似简单,但在分布式环境下却是一个需要认真对待的架构问题。对象存储就是互联网时代解决这个问题的标准答案。
:::
**这篇文章会带你学什么?**
学完这章后,你将获得:
- **存储类型认知**:理解块存储、文件存储、对象存储的区别和适用场景
- **对象存储核心概念**:掌握 Bucket、Object、Key、Pre-signed URL 等核心概念
- **上传方案设计**:学会客户端直传 vs 服务端中转的方案选型
- **CDN 加速原理**:理解 CDN 如何加速静态资源的全球分发
- **最佳实践**:掌握文件命名、权限控制、生命周期管理等实战技巧
| 章节 | 内容 | 核心概念 |
|-----|------|---------|
| **第 1 章** | 存储类型对比 | 块存储、文件存储、对象存储 |
| **第 2 章** | 对象存储核心概念 | Bucket、Object、Key、元数据 |
| **第 3 章** | 文件上传方案 | 客户端直传、Pre-signed URL |
| **第 4 章** | CDN 加速 | 边缘节点、缓存策略、回源 |
| **第 5 章** | 最佳实践 | 命名规范、权限、生命周期 |
---
## 0. 全景图:为什么不能把文件存在服务器本地?
刚开始做项目时,把用户上传的文件存在服务器本地目录是最直觉的做法。但随着项目发展,你会遇到一系列问题:
- **磁盘空间有限**:服务器磁盘总会满,扩容麻烦
- **多服务器不共享**:负载均衡后,用户请求可能打到不同服务器,文件找不到
- **没有备份**:服务器挂了,文件就丢了
- **没有 CDN**:全球用户访问同一台服务器,速度慢
::: tip 对象存储的核心价值
对象存储(如 AWS S3、阿里云 OSS)解决了所有这些问题:**容量无限、全球可访问、自动备份、天然支持 CDN**。它已经成为互联网应用存储文件的事实标准。
:::
---
## 1. 存储类型对比:块、文件、对象
计算机世界有三种主要的存储方式,它们解决不同层次的问题。
<FileStorageTypeDemo />
| 维度 | 块存储 | 文件存储 | 对象存储 |
|------|--------|---------|---------|
| 数据单位 | 固定大小的块 | 文件 + 目录 | 对象(Key-Value |
| 访问协议 | iSCSI/FC | NFS/SMB | HTTP REST API |
| 性能 | 最高(毫秒级) | 中等 | 较低(但够用) |
| 扩展性 | 有限 | 中等 | 近乎无限 |
| 成本 | 最高 | 中等 | 最低 |
| 典型场景 | 数据库 | 共享文件 | 图片/视频/备份 |
::: tip 简单记忆
- **块存储**像硬盘——给数据库用
- **文件存储**像网络共享文件夹——给多台服务器共享配置用
- **对象存储**像网盘——给用户上传的图片、视频用
:::
---
## 2. 对象存储核心概念
对象存储的数据模型非常简单:**Bucket(桶)** 是容器,**Object(对象)** 是文件,每个对象通过唯一的 **Key(键)** 来标识。
```
my-app-bucket/ ← Bucket(桶)
├── avatars/user-123.jpg ← Object Key
├── avatars/user-456.png ← Object Key
├── reports/2024/q1-report.pdf ← Object Key"目录"只是 Key 的前缀)
└── uploads/temp/file.zip ← Object Key
```
| 概念 | 说明 | 示例 |
|------|------|------|
| Bucket | 存储容器,全局唯一命名 | `my-app-prod``company-assets` |
| Object | 存储的文件本体 + 元数据 | 一张图片、一个 PDF |
| Key | 对象的唯一标识符 | `avatars/user-123.jpg` |
| 元数据 | 对象的附加信息 | Content-Type、自定义标签 |
| ACL | 访问控制列表 | public-read、private |
| Pre-signed URL | 临时授权访问链接 | 有效期 15 分钟的上传/下载链接 |
::: tip 对象存储没有真正的"目录"
`avatars/user-123.jpg` 中的 `avatars/` 不是目录,只是 Key 的前缀。对象存储是扁平结构,所有对象在同一层级。控制台显示的"文件夹"只是按前缀分组的视觉效果。
:::
---
## 3. 文件上传方案:谁来传文件?
文件上传有两种主流方案:服务端中转和客户端直传。对于大多数场景,**客户端直传**是更优的选择。
<FileUploadFlowDemo />
::: tip 客户端直传的优势
1. **节省服务器带宽**:文件不经过你的服务器,直接到 OSS
2. **避免超时**:大文件上传不会触发 Nginx/网关的超时限制
3. **降低服务器负载**:服务器只需要签发凭证,不需要处理文件流
4. **支持断点续传**:OSS 原生支持分片上传,前端可以实现断点续传
实现步骤:前端请求后端获取 Pre-signed URL → 前端用这个 URL 直接上传到 OSS → OSS 回调通知后端
:::
---
## 4. CDN 加速:让全球用户都快
当你的用户遍布全球时,从单一源站下载文件会很慢。CDNContent Delivery Network)通过在全球部署边缘节点,将文件缓存到离用户最近的节点,大幅降低访问延迟。
<CDNAccelerationDemo />
| CDN 概念 | 说明 |
|---------|------|
| 边缘节点 | 分布在全球各地的缓存服务器 |
| 回源 | 边缘节点没有缓存时,向源站请求文件 |
| 缓存命中率 | 请求被边缘节点直接响应的比例,越高越好 |
| TTL | 缓存有效期,过期后需要重新回源 |
| 缓存刷新 | 主动清除边缘节点的缓存,让新文件生效 |
::: tip CDN 最佳实践
- **文件名加 hash**`logo.a3f2b1.png` 而不是 `logo.png`,这样更新文件时不需要刷新缓存
- **设置合理的 TTL**:静态资源(JS/CSS/图片)设长 TTL1年),HTML 设短 TTL5分钟)
- **开启 Gzip/Brotli 压缩**:文本类资源压缩后体积减少 60-80%
:::
---
## 5. 最佳实践
| 实践 | 说明 | 示例 |
|------|------|------|
| Key 命名规范 | 用有意义的前缀组织文件 | `{type}/{date}/{uuid}.{ext}` |
| 避免热点 Key | 不要用递增数字开头 | 用 UUID 或 hash 前缀 |
| 权限最小化 | Bucket 默认 private | 只对需要公开的文件设置 public-read |
| 生命周期规则 | 自动清理过期文件 | 临时文件 7 天后自动删除 |
| 跨域配置 | 前端直传需要配置 CORS | 允许你的域名 PUT/POST |
| 服务端加密 | 敏感文件开启 SSE | SSE-S3 或 SSE-KMS |
---
## 总结
文件存储是每个 Web 应用都会遇到的基础问题。对象存储以其无限容量、低成本、高可用的特性,成为了互联网应用的标准选择。
回顾本章的关键要点:
1. **三种存储类型**:块存储给数据库、文件存储给共享、对象存储给用户文件
2. **对象存储模型**Bucket + Key + Object,扁平结构,HTTP API 访问
3. **客户端直传**Pre-signed URL 方案,文件不经过服务器,高效省资源
4. **CDN 加速**:边缘节点缓存 + 文件名 hash,让全球用户都快
5. **安全与管理**:权限最小化、生命周期规则、服务端加密
## 延伸阅读
- [AWS S3 开发者指南](https://docs.aws.amazon.com/s3/) - 对象存储的标杆文档
- [阿里云 OSS 最佳实践](https://help.aliyun.com/document_detail/31853.html) - 国内最常用的对象存储
- [MinIO 文档](https://min.io/docs/minio/linux/index.html) - 开源的 S3 兼容对象存储
- [Cloudflare R2](https://developers.cloudflare.com/r2/) - 零出口费用的对象存储
- [Pre-signed URL 详解](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) - 客户端直传的核心机制