Webman分片上传不能用$_POST传元数据,因multipart请求中PHP默认解析易出错;应通过Header(如X-File-Hash)传递,并用$request->header()获取;存储需以file_hash为目录、flock加锁防并发;合并前须MD5校验+连续索引验证,流式fwrite写入,禁用全量加载。

Webman 默认不内置分片上传和断点续传逻辑,但它的事件驱动架构和灵活的中间件机制,让 PHP 层实现这套流程比 Laravel 或 ThinkPHP 更轻量、更可控——关键在于别把 chunk 当普通文件处理,也别依赖 $_POST。
Webman 接收分片时为什么不能用 $_POST 传元数据
分片上传的元数据(如 chunk_index、total_chunks、file_hash)如果塞进 $_POST,在 Webman 的 Request 对象里可能被解析失败或丢失,尤其当请求体是 multipart/form-data 且含二进制 chunk 时,PHP 的默认解析容易出错。Webman 基于 Swoole,对原始请求体控制更强,推荐直接读取原始输入流或用 Header 传递元数据。
- 前端应通过 HTTP Header 发送关键字段:
X-File-Hash、X-Chunk-Index、X-Total-Chunks - Webman 后端用
$request->header('x-file-hash')获取,稳定可靠 - 避免用
$_FILES['chunk']['tmp_name']直接操作——Swoole 下临时文件路径不可靠,应调用$request->file('chunk')?->getTmpName()并立即移动 - 若前端坚持 POST body 传元数据,需手动解析
file_get_contents('php://input'),但仅适用于非 multipart 场景
如何在 Webman 中安全存储分片并防止并发冲突
Webman 常驻内存运行,多 worker 并发写入同一目录时,mkdir 和 file_put_contents 若无防护,极易导致目录创建失败或分片覆盖。必须用原子操作隔离每个上传会话。
- 以
file_hash为根目录名,用mkdir($dir, 0755, true)创建,但需检查返回值是否 false 并捕获 warning - 分片文件名固定为
$chunkIndex(纯数字),不加扩展名,避免 mime 类型干扰 - 写入前用
flock($fp, LOCK_EX)锁定目标分片文件句柄(即使只写一次,也防极端并发) - 临时目录建议放在
runtime/chunks/下,而非系统/tmp,避免被清理工具误删
Webman 怎么判断所有分片已收齐并触发合并
不能依赖 count(glob(...)) === $total 这种简单判断:glob 可能漏匹配、文件系统延迟、或存在残留脏数据。Webman 需主动校验+状态兜底。
立即学习“PHP免费学习笔记(深入)”;
- 合并前先 scandir 目录,过滤出纯数字文件名,再 cast 为 int 数组并排序,确认连续且数量匹配
- 对每个分片调用
md5_file(),与前端传来的X-Chunk-MD5Header 比对(前端应在切片后立刻计算并带上) - 合并操作必须用
fopen($final, 'wb')+fwrite()流式写入,禁用file_get_contents全量加载——否则 2GB 文件直接 OOM - 合并成功后,用
array_map('unlink', $chunkFiles)清理,再rmdir($chunkDir);失败则保留目录供重试
Webman 断点续传接口怎么设计才不被绕过
“查询已传分片”这个接口如果只校验 file_hash 就返回列表,攻击者可枚举哈希暴力探测他人上传进度。必须绑定会话上下文或时效性验证。
- 接口路径例如
/api/resume?file_hash=abc123,但服务端需检查该 hash 是否关联到当前用户 ID(从 token 解析) - 或要求前端额外提供
X-Upload-Timestamp,服务端只返回 24 小时内有写入记录的分片 - 返回的分片索引数组必须严格排序,且不含任何服务端生成的额外字段(如时间戳),避免泄露存储结构
- 不要在响应里暴露
chunkDir物理路径、服务器时间等敏感信息
最易被忽略的是分片合并时的文件锁和校验闭环:没锁,多 worker 同时合并会写乱;没校验,网络丢包或磁盘错误会导致最终文件损坏却无感知。这两个动作不是可选项,是 Webman 高并发环境下保数据一致性的底线。



















