PHP组装多Chunk上传文件时出现损坏的问题求解
问题排查与解决方案
针对大文件分块数超过10后组装损坏的问题,核心排查方向聚焦在分块顺序、完整性校验、写入逻辑这几个点,以下是可落地的修复方案:
1. 强制按分块序号顺序拼接(最常见诱因)
前端并行上传分块时,后端若未按序号排序就直接追加写入,会导致大文件分块多了后顺序混乱,直接破坏文件结构。
- 后端
uploadChunk函数必须先验证所有分块是否上传完成,再严格按chunkIndex(从0开始)的顺序拼接:
// 假设接收参数:chunkIndex、totalChunks、fileHash(文件唯一标识)、chunkData $tempDir = './temp_chunks/'; @mkdir($tempDir, 0777, true); // 确保临时目录存在 $chunkPath = $tempDir . $fileHash . '_' . $chunkIndex; // 先保存单个分块到临时文件 file_put_contents($chunkPath, file_get_contents('php://input')); // 检查所有分块是否已上传 $allChunksReady = true; for ($i = 0; $i < $totalChunks; $i++) { if (!file_exists($tempDir . $fileHash . '_' . $i)) { $allChunksReady = false; break; } } // 所有分块齐了,按序号顺序拼接 if ($allChunksReady) { $targetPath = './uploads/' . $fileName; $fp = fopen($targetPath, 'wb'); // 用wb模式覆盖或创建新文件 for ($i = 0; $i < $totalChunks; $i++) { $chunkContent = file_get_contents($tempDir . $fileHash . '_' . $i); fwrite($fp, $chunkContent); unlink($tempDir . $fileHash . '_' . $i); // 写完删除临时分块 } fclose($fp); rmdir($tempDir); // 清理空目录 }
2. 增加分块完整性校验
网络波动可能导致部分分块传输不完整,小文件分块少不易触发,大文件分块多了概率陡增。
- 前端上传每个分块时,计算分块的SHA-1/MD5哈希,随分块一起传给后端
- 后端接收后,计算本地分块的哈希值,与前端传入的对比,不一致则要求重传该分块
前端代码片段:
async function getChunkHash(chunkBlob) { const buffer = await chunkBlob.arrayBuffer(); const hashBuffer = await crypto.subtle.digest('SHA-1', buffer); return Array.from(new Uint8Array(hashBuffer)) .map(b => b.toString(16).padStart(2, '0')) .join(''); } // 上传分块时携带哈希 const chunkHash = await getChunkHash(chunk); const formData = new FormData(); formData.append('chunkData', chunk); formData.append('chunkIndex', index); formData.append('chunkHash', chunkHash); // 其他必要参数... await fetch('/uploadChunk', { method: 'POST', body: formData });
3. 修正文件写入模式
禁止直接在目标文件上并行追加写入,必须先将分块保存到临时文件,待所有分块上传完成后再统一拼接。避免用a模式(追加),改用wb模式创建新文件或覆盖原有文件,防止写入重叠。
4. 校验分块大小一致性
确保除最后一个分块外,其余分块的大小完全一致(比如你设置的1MB),前端切割逻辑要严谨:
const chunkSize = 1024 * 1024; // 1MB const chunks = []; for (let i = 0; i < file.size; i += chunkSize) { chunks.push(file.slice(i, i + chunkSize)); } const totalChunks = chunks.length; // 确保totalChunks参数和实际分块数一致
5. 检查服务器临时目录状态
- 查看PHP错误日志,确认是否有临时分块写入失败的权限或磁盘空间问题
- 确保临时目录
./temp_chunks/拥有读写权限,服务器磁盘剩余空间足够容纳所有临时分块
内容的提问来源于stack exchange,提问作者halocedark
相关产品推荐
相关产品推荐

