分片上传需前端计算每片SHA-256并校验,C++后端用轻量框架接收、磁盘追加写入临时分片,合并前锁状态并校验索引与哈希,预览应边传边解码首GOP关键帧生成缩略图。

分片上传前必须校验文件是否被篡改
直接按字节切片上传,服务端无法验证文件完整性。用户中途修改文件、网络传输损坏、浏览器读取缓存偏差都会导致最终拼接失败。必须在前端计算每个分片的哈希(如 SHA-256),并传给服务端做二次校验。
关键点:
-
FileReader读取Blob.slice()得到的子块,不能直接用ArrayBuffer做哈希——需用crypto.subtle.digest()(现代浏览器)或spark-md5(兼容 IE/旧版) - 不要对整个大文件一次性调
file.arrayBuffer(),会 OOM;必须分片读 + 流式哈希 - 服务端收到分片后,先比对
sha256字段,不一致直接 400,不写磁盘
C++ 后端如何接收并暂存分片文件
HTTP 接口收的是 multipart/form-data 或 raw binary,C++ 没有内置 multipart 解析器,别硬啃 RFC。用 cpp-httplib 或 crow 这类轻量框架,配合 std::ofstream 以 std::ios::binary | std::ios::app 模式追加写入临时分片文件。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 分片文件名格式固定为
{upload_id}_{part_index}.part,upload_id由前端生成(如 UUID),避免并发冲突 - 不要用内存 buffer 缓存整个分片——100MB 分片 = 100MB 内存占用,直接
write()到磁盘 - 写入前检查磁盘剩余空间:
statvfs()(Linux)或GetDiskFreeSpaceEx()(Windows) - 设置 ulimit -n 防止打开过多文件句柄(尤其高并发上传时)
合并分片时避免竞态和重复触发
前端上传完所有分片后,发一个 /merge?upload_id=xxx 请求。服务端不能简单遍历 *.part 文件然后 cat,必须加锁 + 状态检查。
常见错误:
- 多个请求同时触发 merge → 产生重复合并或文件损坏
- 前端重试导致部分分片重复上传 → 合并时多出冗余块
- 分片上传顺序乱序 → 直接按文件名排序会错(
1, 10, 2)
正确做法:
- 用
std::shared_mutex或文件锁(flock())保护upload_id对应的合并状态 - 维护一个
uploaded_parts.json记录已接收的part_index和sha256,merge 前校验数量和哈希全匹配 - 分片索引统一用零填充字符串(
0001,0002)或整数存储,排序前转int
预览功能不是“上传完再处理”,而是边传边解码
用户等 2GB 视频上传完再预览?体验极差。真正可行的是:首片上传成功后,立即提取其关键帧(如第一 GOP)生成缩略图,用 libavcodec + libswscale 实现。
限制与取舍:
- 只解码 I 帧,跳过 P/B 帧,用
AVSEEK_FLAG_BACKWARD定位最近关键帧 - 分辨率强制缩到 320x180,避免解码耗时过长
- 不等全部分片,只要前 2~3 片(含 SPS/PPS)就足够解析视频基础参数(宽高、编码格式)
- 缩略图存为
{upload_id}_preview.jpg,前端轮询该路径,返回 404 就继续等
复杂点在于:不同容器(MP4/AVI/FLV)的分片边界不一定对齐 GOP,所以首片未必含完整关键帧。得在 C++ 层做简易 demux,定位第一个 AVPacket 的 flags & AV_PKT_FLAG_KEY。



















