为什么使用js、php和apache进行视频切片上传时无法上传48MB以上文件?如何解决这个问题?

为什么使用js、php和apache进行视频切片上传时无法上传48MB以上文件?如何解决这个问题?
最新回答
风软一江水

2021-05-24 15:18:38

使用JS、PHP和Apache进行视频切片上传时无法上传48MB以上文件的主要原因是前端代码中FormData对象重复使用导致请求体膨胀,以及Apache配置限制未调整。 以下是具体分析和解决方案:

问题原因
  • 前端代码缺陷

    原始代码中仅初始化一次FormData对象,后续每次切片上传都在同一对象上追加数据,导致请求体包含所有切片数据,迅速超过Apache限制。

    触发Apache的fcgidmaxrequestlen限制,返回500错误。

  • 服务器配置不足

    Apache的php_value upload_max_filesize、post_max_size或fcgidmaxrequestlen未设置为足够大的值(默认可能低于48MB)。

  • 后端内存溢出风险

    PHP合并文件时若一次性读取所有切片数据,可能导致内存不足。

解决方案1. 前端JavaScript代码优化
  • 关键修改:每次发送请求前创建新的FormData和XMLHttpRequest对象,避免数据累积。
  • 代码示例:function videoFileUpload() { const CHUNK_SIZE = 1024 * 1024; // 1MB切片大小 let start = 0; let blobNum = 1; let isStop = false; this.start = function() { const file = files.files[0]; sendFile(file, 0); // 初始调用 }; function sendFile(file, startPos) { if (isStop) return; const xhr = new XMLHttpRequest(); const formData = new FormData(); // 每次新建FormData const end = startPos + CHUNK_SIZE; const blob = file.slice(startPos, end); formData.append('file', blob); formData.append('blobNum', blobNum); formData.append('totalBlobNum', Math.ceil(file.size / CHUNK_SIZE)); formData.append('fileName', file.name); xhr.open('POST', '/upload.php', true); xhr.onload = function() { if (xhr.status === 200 && blobNum < Math.ceil(file.size / CHUNK_SIZE)) { blobNum++; sendFile(file, end); // 递归上传下一片 } }; xhr.send(formData); }}
2. 服务器配置调整
  • 修改Apache/PHP参数

    upload_max_filesize:设置为大于48MB(如100M)。

    post_max_size:需大于upload_max_filesize(如101M)。

    fcgidmaxrequestlen:调整为足够大的值(如104857600,即100MB)。

    修改方式

    在Apache配置文件(如httpd.conf或虚拟主机配置)中添加:php_value upload_max_filesize 100Mphp_value post_max_size 101MFcgidMaxRequestLen 104857600

    或通过.htaccess文件(需Apache支持mod_php):php_value upload_max_filesize 100Mphp_value post_max_size 101M

3. PHP后端代码优化
  • 分批合并文件:避免一次性读取所有切片,改用流式处理或临时文件存储。
  • 示例逻辑:// upload.php 示例片段$tempDir = '/tmp/uploads/';$chunk = $_FILES['file']['tmp_name'];$blobNum = $_POST['blobNum'];$fileName = $_POST['fileName'];// 保存切片到临时目录move_uploaded_file($chunk, $tempDir . $fileName . '.part' . $blobNum);// 合并条件:所有切片上传完成后执行if ($_POST['blobNum'] === $_POST['totalBlobNum']) { $finalPath = '/uploads/' . $fileName; for ($i = 1; $i <= $_POST['totalBlobNum']; $i++) { $partPath = $tempDir . $fileName . '.part' . $i; file_put_contents($finalPath, file_get_contents($partPath), FILE_APPEND); unlink($partPath); // 删除临时文件 }}
4. 其他建议
  • 使用专业上传库:如Flysystem或Resumable.js,简化大文件处理逻辑。
  • 监控上传进度:通过xhr.upload.onprogress实现进度条,提升用户体验。
总结

通过前端每次创建新的FormData对象调整Apache/PHP配置优化后端合并逻辑,可解决48MB以上文件上传失败问题。核心在于避免请求体膨胀和服务器资源耗尽,同时确保配置与代码逻辑匹配。