Skip to content

Commit 2a21270

Browse files
committed
feat: file storage
1 parent 14ef3f3 commit 2a21270

1 file changed

Lines changed: 69 additions & 38 deletions

File tree

  • docs/blog/golang/architectural

docs/blog/golang/architectural/3.mdx

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,89 +5,120 @@ sidebar_position: 3
55
---
66

77

8-
# 基于 Go 与 S3 的高效文件上传实现:支持断点续传与秒传
8+
# 基于 Go 与 S3 的高效大文件上传方案 —— 支持断点续传与秒传
99

10+
在现代 App 与 Web 应用中,大文件上传是常见且关键的功能。为应对传输中可能出现的中断、重复上传等问题,我们设计并实现了一套基于 **Go 服务端 + S3 存储** 的文件上传机制。该方案支持**断点续传****秒传** ,并具备良好的**可扩展性****极简客户端 SDK** ,实现客户端与 S3 直连,**数据流不经 API 服务中转**
1011

11-
在现代 App 或 Web 应用中,上传大文件已成为常见需求。为了应对大文件传输过程中的各种挑战,我们实现了一套基于 Go 服务端 + S3 存储的文件上传机制。该方案不仅支持断点续传和秒传,还支持服务器端扩展其他存储系统,同时保持 SDK 极简,客户端与存储系统直连,数据不经由 API 服务中转。
1212

13+
## ✨ 设计目标
1314

14-
## 设计目标
1515

16+
- ✅ 极简 SDK:客户端无需存储系统适配逻辑
1617

17-
- 减少 SDK 体积与复杂度
18+
- ✅ 降低服务器负载:文件流量不经由 API 服务
1819

19-
- 降低服务端压力,文件流量不经过 API 服务
20+
- ✅ 支持断点续传与秒传,提升用户体验
2021

21-
- 支持断点续传、秒传
22+
- ✅ 兼容任意 S3 接口,易于接入多种对象存储
2223

23-
- 灵活支持多种 S3 兼容存储系统
24+
- ✅ 可拓展支持非 S3 的 HTTP PUT 分片上传
2425

25-
- 可拓展支持非 S3 的 PUT 上传接口
2626

2727

28-
## 上传流程详解
28+
## 📦 上传流程
2929

3030

31-
整个上传过程分为以下几个关键步骤
31+
上传流程共分为五步
3232

33-
1. 获取分片大小 `/object/part_limit`
34-
客户端 SDK 会首次请求接口 `/object/part_limit` 获取服务器定义的分片大小(如 5MB),并将该值缓存。
3533

36-
### 2. 计算分片哈希与文件整体哈希
34+
### 1. 获取分片大小
3735

36+
接口:`GET /object/part_limit`
3837

39-
根据分片大小,客户端将文件切分为多个 part,并计算每一块的哈希值。随后,将所有分片哈希拼接,计算出文件的整体 hash(用于秒传检测)
38+
客户端首次上传前,请求服务端获取推荐的分片大小(如 5MB),并进行缓存
4039

41-
3. 初始化上传 `/object/initiate_multipart_upload`
4240

43-
- 客户端向服务端发起初始化上传请求。
41+
### 2. 计算文件哈希
4442

45-
- 若该文件已存在(通过 hash 匹配),服务端直接返回下载地址
43+
客户端将文件按分片大小切分,并计算每个分片的哈希值。然后将所有分片哈希拼接,最终计算出文件整体哈希(`file_hash`),用于秒传判断
4644

47-
- 若文件不存在,返回每一分片所需的上传签名,包括分片的上传 URL、Header、编号等信息。
4845

46+
### 3. 初始化上传
4947

50-
### 4. 上传分片(客户端直传 S3)
48+
接口:`POST /object/initiate_multipart_upload`
5149

50+
客户端提交文件整体信息(如 hash、文件名、大小):
5251

53-
客户端使用签名信息,将分片通过 HTTP PUT 上传到指定的 S3 地址。上传过程中的每一块信息(如 ETag、PartNumber)被 SDK 记录本地,以支持断点续传。
5452

53+
- 若服务器发现该文件已存在(通过 `file_hash` 判断),则返回秒传成功的下载地址;
5554

55+
- 若不存在,则返回每个分片的上传签名信息,包括:
5656

57-
> 上传和下载过程中文件流不经过 API 服务,均为客户端直连 S3。
5857

59-
5. 完成上传 `/object/complete_multipart_upload`
58+
- 分片上传 URL
6059

61-
当所有分片上传完毕后,SDK 调用接口通知服务端合并。
60+
- 必需的 Header(如 `Content-Type`, `Authorization`
6261

63-
服务端校验所有块哈希与整体 hash,校验成功后通知 S3 合并,并返回最终文件的访问 URL。
62+
- `PartNumber` 等标识
6463

6564

66-
## 下载流程
65+
### 4. 上传分片(直传 S3)
6766

68-
客户端通过从 API 获取的文件 URL 进行下载,该地址为临时的带签名的 S3 地址,可设置权限控制或时效性。
6967

70-
## 特别说明
68+
客户端使用返回的签名信息,将每个分片通过 HTTP PUT 直接上传至 S3,对应:
7169

72-
- 上传成功返回的 URL 为 API 地址,访问该地址会重定向到带签名的真实 S3 地址。你也可以在这一步加权限判断。
7370

74-
- 所有文件上传和下载都不走 API 流量,仅用于控制和调度逻辑。
71+
- 上传过程中记录每一分片的 ETag 与 PartNumber
7572

76-
## 特性总结
73+
- SDK 持久化这些信息,实现断点续传
7774

7875

79-
### ✅ 支持秒传
8076

81-
文件 hash 校验可快速跳过上传过程
77+
> ⚠️ 文件内容始终不经由服务端,仅签名和元数据走 API
8278
83-
### ✅ 支持断点续传
8479

85-
客户端缓存上传信息,App 关闭后可继续上传。
80+
### 5. 完成上传
8681

87-
### ✅ SDK 极简
82+
接口:`POST /object/complete_multipart_upload`
8883

89-
SDK 不实现任何签名逻辑,所有签名由服务端统一生成。这样可支持任意 HTTP PUT 兼容的对象存储系统,而不需要修改客户端代码
84+
客户端上传所有分片成功后,调用此接口提交分片信息列表
9085

91-
## 可扩展性
9286

93-
只要新的存储系统支持通过 HTTP PUT 上传分片,服务端即可为其实现签名生成逻辑,而无需更改客户端 SDK,这让整个系统拥有很高的可移植性。
87+
- 服务端校验每个分片哈希及整体 hash
88+
89+
- 校验通过后,发起 S3 的合并操作
90+
91+
- 最终返回文件的访问地址(可跳转到签名 S3 URL)
92+
93+
94+
## ⬇️ 下载流程
95+
96+
97+
客户端下载时,从服务端获取临时签名下载地址(S3 Pre-signed URL),可设置权限与有效期控制。该地址可通过 API 统一跳转实现权限校验。
98+
99+
100+
101+
## ✅ 特性一览
102+
103+
| 特性 | 说明 |
104+
| --- | --- |
105+
| 秒传支持 | 基于文件 hash 实现上传秒跳过 |
106+
| 断点续传 | 支持断线、异常退出后继续上传 |
107+
| 极简 SDK | 客户端无需签名逻辑,仅执行 PUT |
108+
| 存储兼容性强 | 支持任意兼容 HTTP PUT 的对象存储 |
109+
| 高可拓展性 | 可快速接入其他上传协议和存储系统 |
110+
111+
112+
113+
## ⚙️ 可扩展性设计
114+
115+
116+
该方案以“服务端统一生成签名 + 客户端通用 PUT 上传”为核心架构,只要目标存储系统支持分片上传并接受带签名的 PUT 请求,即可无缝接入:
117+
118+
119+
- 支持 Amazon S3、MinIO、阿里云 OSS、腾讯云 COS 等
120+
121+
- 也可扩展支持其它上传服务
122+
123+
124+
客户端代码不变,服务端扩展签名生成逻辑即可。

0 commit comments

Comments
 (0)