Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 120 additions & 1 deletion docs/blog/golang/architectural/3.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,124 @@
---
title: 文件断点续传的设计
title: 文件存储
hide_title: true
sidebar_position: 3
---


# 基于 Go 与 S3 的高效文件上传方案 —— 支持断点续传与秒传

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


## ✨ 设计目标


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

- ✅ 降低服务器负载:文件流量不经由 API 服务

- ✅ 支持断点续传与秒传,提升用户体验

- ✅ 兼容任意 S3 接口,易于接入多种对象存储

- ✅ 可拓展支持非 S3 的 HTTP PUT 分片上传



## 📦 上传流程


上传流程共分为五步:


### 1. 获取分片大小

接口:`GET /object/part_limit`

客户端首次上传前,请求服务端获取推荐的分片大小(如 5MB),并进行缓存。


### 2. 计算文件哈希

客户端将文件按分片大小切分,并计算每个分片的哈希值。然后将所有分片哈希拼接,最终计算出文件整体哈希(`file_hash`),用于秒传判断。


### 3. 初始化上传

接口:`POST /object/initiate_multipart_upload`

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


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

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


- 分片上传 URL

- 必需的 Header(如 `Content-Type`, `Authorization`)

- `PartNumber` 等标识


### 4. 上传分片(直传 S3)


客户端使用返回的签名信息,将每个分片通过 HTTP PUT 直接上传至 S3,对应:


- 上传过程中记录每一分片的 ETag 与 PartNumber

- SDK 持久化这些信息,实现断点续传



> ⚠️ 文件内容始终不经由服务端,仅签名和元数据走 API。


### 5. 完成上传

接口:`POST /object/complete_multipart_upload`

客户端上传所有分片成功后,调用此接口提交分片信息列表。


- 服务端校验每个分片哈希及整体 hash

- 校验通过后,发起 S3 的合并操作

- 最终返回文件的访问地址(可跳转到签名 S3 URL)


## ⬇️ 下载流程


客户端下载时,从服务端获取临时签名下载地址(S3 Pre-signed URL),可设置权限与有效期控制。该地址可通过 API 统一跳转实现权限校验。



## ✅ 特性一览

| 特性 | 说明 |
| --- | --- |
| 秒传支持 | 基于文件 hash 实现上传秒跳过 |
| 断点续传 | 支持断线、异常退出后继续上传 |
| 极简 SDK | 客户端无需签名逻辑,仅执行 PUT |
| 存储兼容性强 | 支持任意兼容 HTTP PUT 的对象存储 |
| 高可拓展性 | 可快速接入其他上传协议和存储系统 |



## ⚙️ 可扩展性设计


该方案以“服务端统一生成签名 + 客户端通用 PUT 上传”为核心架构,只要目标存储系统支持分片上传并接受带签名的 PUT 请求,即可无缝接入:


- 支持 Amazon S3、MinIO、阿里云 OSS、腾讯云 COS 等

- 也可扩展支持其它上传服务


客户端代码不变,服务端扩展签名生成逻辑即可。
2 changes: 1 addition & 1 deletion docs/sdks/callback/onInputStatusChanged.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ toc_max_heading_level: 2

| 名称 | 类型 | 描述 |
| --------- | --------------------------------------------------- | -------- |
| InputStatusChangedData | [InputStatusChangedData](docs/sdks/class/conversation/inputStatusChangedData.mdx) | 群聊信息 |
| InputStatusChangedData | [InputStatusChangedData](docs/sdks/class/conversation/inputStatusChangedData.mdx) | 用户输入状态改变 |
2 changes: 1 addition & 1 deletion docs/sdks/class/conversation/inputStatusChangedData.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ toc_max_heading_level: 2
| ----------------- | -------------------------------------------------- | --------------------------------------------------------------------- |
| UserID | string | 用户ID |
| ConversationID | string | 会话ID |
| PlatformIDs | `[]`[IMPlatformID](/docs/sdks/enum/platform.mdx) | 平台号 |
| PlatformIDs | `[]`[IMPlatformID](/docs/sdks/enum/platform.mdx) | 正在输入的平台ID |