beego 默认不支持大文件分片上传,因 getfile 依赖 multipart 解析,受 maxmemory 和 maxuploadsize 限制,超限直接返回 413;需绕过表单解析,用 requestbody 原始读取分片流,并自行处理元信息、存储、合并及状态管理。

Beego 默认不支持大文件分片上传,直接用 GetFile 会触发 413 Request Entity Too Large 或内存溢出;进度条也必须绕过 Beego 的默认表单解析流程,改用原生 XMLHttpRequest + 分片流式上传才能实现真实进度反馈。
为什么不能直接用 Beego 的 GetFile 处理大文件
Beego 的文件上传走的是标准 multipart/form-data 解析路径,所有数据先被读入内存或临时文件,再交给 Controller。这带来两个硬限制:
-
web.MaxMemory(默认 4MB)决定多少内容进内存;超过则落盘,但整个请求体仍需完整接收 -
MaxUploadSize是总大小上限,一旦超限,Beego 直接返回413,连路由都进不了 Controller - 没有上传中止、重试、分片标识等语义,无法支撑断点续传或秒传逻辑
所以,大文件上传必须绕过 Beego 的表单解析层——前端不再用 <form></form> 提交,后端也不调用 GetFile,而是用 Ctx.Input.RequestBody 原始读取二进制流,并自行解析分片元信息(如 chunkIndex、totalChunks、fileId)。
如何在 Beego 中接收分片并拼接文件
你需要一个专用的分片上传接口,比如 /api/upload/chunk,它不依赖 GetFile,而是手动处理原始 body:
- 用
ctx.Input.RequestBody获取原始字节流,避免 Beego 自动解析 multipart - 从 URL query 或 header 中提取分片参数:
chunkIndex=5&totalChunks=20&fileId=abc123 - 将分片写入临时目录(如
./uploads/chunks/abc123_5),不要合并到内存 - 上传完成后,由另一个接口(如
/api/upload/merge)按序读取所有分片,拼成完整文件并计算 MD5
示例关键代码片段:
func (c *UploadController) UploadChunk() {
fileId := c.GetString("fileId")
chunkIndex := c.GetInt("chunkIndex")
totalChunks := c.GetInt("totalChunks")
data := c.Ctx.Input.RequestBody
chunkPath := fmt.Sprintf("./uploads/chunks/%s_%d", fileId, chunkIndex)
os.MkdirAll("./uploads/chunks", 0755)
ioutil.WriteFile(chunkPath, data, 0644)
// 记录已上传索引(可用 Redis 或本地 map+定时清理)
cacheKey := "upload:" + fileId
redisClient.SAdd(cacheKey, strconv.Itoa(chunkIndex))
c.Data["json"] = map[string]interface{}{"success": true}
c.ServeJSON()
}
前端如何实现分片上传 + 实时进度条
进度条不是靠 Beego 返回的响应算出来的,而是靠 XMLHttpRequest.upload.onprogress 监听每个分片自身的上传过程:
- 每个分片单独发起一个
POST请求,URL 带上?fileId=xxx&chunkIndex=3 - 监听该请求的
xhr.upload.onprogress,用e.loaded / e.total更新当前分片进度 - 整体进度 = 已完成分片数 × 分片大小 + 当前分片已上传字节数 / 总文件大小
- 切片用
file.slice(start, end),注意浏览器兼容性(IE 不支持,需降级为 Blob 构造)
关键点:Beego 后端不参与进度计算,只负责收分片;进度完全由前端维护状态机管理,包括失败重试、跳过已传分片(查服务端已存在列表)、暂停恢复等。
容易被忽略的三个落地细节
很多团队卡在“能跑通 demo”但上线就崩,问题往往出在这几个地方:
- 分片并发数没控:前端同时发 20 个分片请求,Beego 默认 HTTP 连接池可能被打满,建议限制在 3–5 路并发
- 临时分片文件没清理:用户中断上传后,
./uploads/chunks/xxx_*残留,需加定时任务或用 Redis TTL 配合清理钩子 - 文件名和类型校验被跳过:分片接口未校验
fileId是否合法、Content-Type是否允许,攻击者可伪造路径写任意文件
真正的难点不在切片或拼接,而在于把分片生命周期(上传中、已成功、已取消、已过期)映射成可查询、可清理、可幂等的状态模型——这个模型必须前后端对齐,且独立于 Beego 的请求生命周期存在。











