You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS+PHP分片上传10MB以上视频无法播放问题排查

分片上传大视频后无法播放的问题排查与修复

核心问题:分片合并顺序错乱

你的PHP代码在合并分片时,使用glob($targetDir . $filename . '.*')获取所有分片文件,但glob返回的文件列表是字符串字典序,而非数字顺序。比如17.6MB的视频会生成18个分片,filename.10会排在filename.2前面,合并后的文件字节顺序完全混乱,导致视频无法播放——但总字节数和原文件一致,所以显示的文件大小正常。

修复代码(PHP):

替换分片获取与排序逻辑,确保按数字索引顺序合并:

// 原代码
$chunks = glob($targetDir . $filename . '.*');

// 修复后:自然排序保证数字顺序
$chunks = glob($targetDir . $filename . '.*');
natsort($chunks); // 按数字大小排序,而非字符串字典序
$chunks = array_values($chunks); // 重置数组索引,避免排序后索引混乱

次要问题:并行上传的不确定性

你的JS代码在循环中直接发送所有分片的XHR请求,属于并行上传。虽然最终所有分片都会到达服务器,但可能导致服务器接收顺序和发送顺序不一致,同时并发请求可能引发服务器资源竞争。建议改为串行上传(上传完一个分片再传下一个),避免潜在问题。

修复代码(JS):

修改processFile函数为串行上传逻辑:

function processFile() {
  if (!file.files[0]) {
    console.error("No file selected.");
    return;
  }

  const TheFile = file.files[0];
  const filename = TheFile.name;
  const filesize = TheFile.size;
  const number_allowed_chunks = Math.ceil(filesize / chunkSize);
  let chunkId = 0;

  // 单个分片上传函数
  function uploadChunk() {
    if (chunkId >= number_allowed_chunks) return;

    const start = chunkId * chunkSize;
    const end = Math.min(start + chunkSize, filesize);
    const chunk = TheFile.slice(start, end);
    const chunkIndex = chunkId + 1;

    const xrequest = new XMLHttpRequest();
    xrequest.open("POST", "chatphp.php", true);

    xrequest.onerror = () => console.error("请求失败:分片", chunkIndex);
    xrequest.upload.addEventListener("error", () => console.error("上传失败:分片", chunkIndex));
    xrequest.upload.addEventListener("progress", ({ loaded, total }) => {
      updateProgress(loaded, total, number_allowed_chunks, chunkIndex);
    });

    // 当前分片上传完成后,启动下一个分片上传
    xrequest.onload = () => {
      chunkId++;
      uploadChunk();
    };

    const formData = new FormData();
    formData.append("chunk", chunk);
    formData.append("chunkIndex", chunkIndex);
    formData.append("fileName", filename);
    formData.append("totalNumber", number_allowed_chunks);
    xrequest.send(formData);
  }

  // 启动串行上传
  uploadChunk();
}

其他潜在问题优化

  1. MD5校验时机调整:原代码先移动分片文件再校验,建议先校验临时文件,确认无误后再移动,避免存储损坏的分片:
// 原代码
if (move_uploaded_file($_FILES['chunk']['tmp_name'], $chunkPath)) {
    $uploadedChunkFile = md5_file($chunkPath);
    if ($uploadedChunkFile != $checksum) {
        echo "Error: Quality check failed";
        $GoAhead = 0;
    }
}

// 修复后
$tempChunk = $_FILES['chunk']['tmp_name'];
$uploadedChunkFile = md5_file($tempChunk);
if ($uploadedChunkFile != $checksum) {
    echo "Error: Quality check failed";
    $GoAhead = 0;
} else {
    if (move_uploaded_file($tempChunk, $chunkPath)) {
        // 后续分片合并逻辑
    }
}
  1. PHP配置检查:确认php.ini中的post_max_size、upload_max_filesize均大于单分片大小(1MB),大文件上传时串行上传可避免触发max_input_vars等并发限制。

内容的提问来源于stack exchange,提问作者Theophilus Tetteh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:02:56