php本身无法实时反馈上传进度,必须由前端用xmlhttprequest.upload.onprogress监听字节级进度,后端仅负责接收分片或校验临时文件;需禁用表单默认提交、增大nginx及php上传限制,并返回json供前端更新ui。

PHP 本身无法实现“实时反馈”,得靠前端配合
PHP 是服务端脚本,处理完请求才返回结果,不可能在上传过程中主动推送进度。所谓“实时反馈”,本质是前端用 XMLHttpRequest 或 fetch 配合 progress 事件监听上传进度,再通过 PHP 提供的临时文件或分片接口做校验和落盘。
常见错误现象:$_FILES 为空、upload_max_filesize 超限、上传卡在 0% 不动——多半是前端没监听 upload.onprogress,或后端直接用了默认表单提交(无 JS 控制)。
- 必须用
FormData构造上传体,不能直接submit()表单 - PHP 端无需特殊扩展,但要确保
post_max_size和upload_max_filesize足够大(如128M) - 若音频较大(>50MB),建议前端分片上传,PHP 接收后合并,否则容易超时或内存溢出
前端如何监听上传进度并更新 UI
核心是绑定 XMLHttpRequest.upload.onprogress,它会在每次底层传输块到达时触发。注意:这个事件只对 PUT 或 POST 有效,且仅当使用 FormData + send() 时可用。
示例关键片段:
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
document.getElementById('progress').innerText = `${percent}%`;
}
};
xhr.open('POST', '/upload.php');
xhr.send(formData);
- 不要依赖
onload判断“是否开始上传”,它只在完成时触发 -
e.loaded是已发送字节数,e.total是总大小(需前端提前file.size获取) - 移动端 Safari 对大文件
onprogress支持不稳定,可加降级逻辑:上传开始后启动定时器模拟进度条
PHP 如何安全接收并验证音频文件
不能只信 $_FILES['audio']['type'],浏览器可伪造 MIME;也不能只看扩展名,得用 finfo_open() 检查二进制头。
实操建议:
- 先检查
$_FILES['audio']['error'] === UPLOAD_ERR_OK,否则直接返回错误(如UPLOAD_ERR_INI_SIZE) - 用
finfo_open(FILEINFO_MIME_TYPE)读取真实类型,只允许audio/mpeg、audio/wav、audio/ogg等白名单 - 重命名文件(如
uniqid() . '.mp3'),避免用户上传shell.php.jpg类攻击文件 - 移动前用
move_uploaded_file(),不用copy()或rename(),防止临时文件被并发覆盖
为什么上传完成后还要返回 JSON 而不是跳转页面
因为前端需要拿到服务端生成的文件路径、时长、封面 URL 等元数据,用于后续播放或展示。如果 PHP 直接输出 HTML 或重定向,进度条就断了,用户看到的是空白页或 404。
标准响应格式应为:
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'success' => true,
'url' => '/uploads/' . $safeName,
'duration' => $duration, // 可用 ffmpeg 命令行提取
'size' => $_FILES['audio']['size']
]);
- 务必设
Content-Type,否则前端response.json()可能解析失败 - PHP 中调
exec('ffprobe -v quiet -show_entries format=duration -of csv=p=0 ' . escapeshellarg($tmpPath), $output)提取时长,注意权限和超时(大文件可能卡住) - 如果上传后要立即转码,别在同一个请求里干——改用消息队列或异步任务,否则用户会等几十秒无响应
最易被忽略的一点:Nginx 默认有 client_max_body_size 限制,即使 PHP 的 upload_max_filesize 调大了,Nginx 仍会直接返回 413 错误,且不触发 PHP 任何逻辑。得同步改 Nginx 配置。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











