Echo框架不支持流式上传,需手动接管Request.Body并用ProgressReader包装后配合multipart.NewReader逐块解析;c.FormFile()和c.MultipartForm()会一次性读取整个请求体,无法监控进度;c.File()是服务端流式下载接口,与上传无关;还需调整HTTP服务器及代理层超时设置,并过滤恶意文件名。

直接结论:Echo 框架本身不提供“流式上传”接口,所谓“流上传”必须手动接管 Request.Body,用 ProgressReader 包装并配合 multipart.NewReader 逐块解析 —— 否则你拿到的永远是上传完成后的文件句柄,进度无从监控。
为什么 c.FormFile() 和 c.MultipartForm() 无法用于流上传
这两个方法会触发 Echo(底层是 net/http)一次性读取整个请求体到内存或临时磁盘,中间不暴露读取过程:
-
c.FormFile()返回的是已落盘/内存的*multipart.FileHeader,此时上传早已结束 -
c.MultipartForm()内部调用ParseMultipartForm(),强制读满MaxMemory或写入临时文件,无法插入进度逻辑 - 若上传超时或客户端中断,你连错误都收不到 —— 因为框架还在等 Body 读完
如何手动实现带进度的 multipart 流式解析
核心是绕过框架自动解析,自己构造 multipart.Reader:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- 先读
c.Request.Header.Get("Content-Length")获取总大小(注意:浏览器上传时通常会发,但 CLI 工具如 curl 需显式加-H "Content-Length: xxx") - 用自定义
ProgressReader包装c.Request.Body,在Read(p []byte)中累加已读字节数,并更新共享状态(如sync.Map以uploadID为 key) - 用该
ProgressReader初始化multipart.NewReader(),再循环调用NextPart()和part.Read() - 务必禁用
c.Request.Body的默认解析:在 handler 开头调用c.Request.Body = progressReader,否则后续读取会冲突
c.File() 不是上传,是下载 —— 别混淆用途
很多人搜“Echo 流上传”却误用 c.File(),这是严重概念错位:
-
c.File()是服务端向客户端**流式响应文件**(即下载),基于http.ServeContent,支持Range请求和断点续传 - 它完全不处理上传逻辑,也不能用来“接收”大文件;上传仍需走
multipart或原始io.Copy接收 - 若你目标是“上传大视频后立刻可播放”,那上传阶段仍需完整接收(哪怕存临时文件),再用
c.File()提供播放路由
容易被忽略的底层约束
即使你实现了 ProgressReader,仍有几个硬性限制必须同步处理:
- Go HTTP Server 默认
ReadTimeout是 30 秒 —— 大文件上传必然超时,必须在e.StartServer()前设置&http.Server{ReadTimeout: 5 * time.Minute} - 代理层(Nginx、Cloudflare)也有独立超时,比如 Nginx 的
client_max_body_size和proxy_read_timeout必须调大 -
multipart解析本身不校验文件名安全性,路径遍历风险仍在 —— 若你把上传文件按原名保存,../../../etc/passwd这类名字必须提前过滤

















