分块上传是将大文件按固定大小切分为多个chunk并携带唯一标识上传,服务端暂存后合并;需客户端管理切片与重传、服务端支持幂等接收与校验;前后端分别通过File API和HTTP Handler实现,并增强断点续传、并发控制、去重清理等健壮性机制。
分块上传不是简单地把文件切开发送,而是将大文件按固定大小(如5MB)分成多个chunk,每个chunk携带唯一标识(如文件唯一ID、chunk序号、总块数),服务端接收后暂存,待所有块收齐再合并。关键点在于:客户端需自行管理切片、顺序、重传;服务端需支持幂等接收、去重校验、临时存储与合并。
浏览器端用File.slice()提取每一块,配合fetch或Axios发送带元数据的POST请求。建议添加断点续传能力——上传前先查服务端已存在哪些块(如G
ET /upload/status?file_id=xxx),跳过已传成功的chunk。
X-File-ID、X-Chunk-Index、X-Total-Chunks、X-Chunk-Hash(可选,用于校验)Promise.allSettled控制并发数(如同时传3块),避免浏览器连接耗尽progress事件更新UI,失败chunk自动加入重试队列(最多2次)用标准http.Handler接收单个chunk,不依赖框架也能高效处理。核心是设计好临时存储路径和状态管理。
file_id和chunk_index,校验Content-Length是否匹配预期(防恶意截断)/tmp/uploads/{file_id}/{chunk_index}(用ioutil.WriteFile或os.Create+io.Copy)GET /upload/status?file_id=xxx接口返回已上传chunk索引列表(从目录读取或查Redis缓存)chunk_index == total-1),触发合并:按序读取所有chunk文件,用io.MultiReader拼接后写入最终目标路径生产环境必须考虑异常场景。例如用户关闭页面导致部分块未传完,或同一文件多次上传。
file_id设置12小时过期时间,用Go定时器或外部任务(如cron)清理/tmp/uploads/下陈旧目录file_id → {uploaded_chunks: [...], uploaded_at: time},避免每次查文件系统^[a-zA-Z0-9_-]{12,32}$格式的file_id),防止路径遍历