上传音频前须检查$_FILES和upload_max_filesize;确保php.ini中upload_max_filesize与post_max_size足够大且enctype为multipart/form-data;用move_uploaded_file()保存并白名单校验扩展名与MIME类型。

上传音频文件前必须检查 $_FILES 和 upload_max_filesize
PHP 上传失败最常见的原因是服务器限制没调,而不是代码写错。上传音频(尤其是 MP3、WAV、M4A)很容易超默认的 2M 限制,直接导致 $_FILES['audio']['error'] === 1(UPLOAD_ERR_INI_SIZE)或 UPLOAD_ERR_NO_FILE(表单提交了但 $_FILES 为空)。
必须确认三件事:
-
php.ini中upload_max_filesize和post_max_size都设得足够大(比如20M),且post_max_size≥upload_max_filesize - 表单
的enctype是"multipart/form-data",缺了这个$_FILES一定为空 - 前端 input 的
name和 PHP 中读取的键名一致,例如对应$_FILES['audio']
用 move_uploaded_file() 保存音频,别用 copy() 或直接读 tmp_name
move_uploaded_file() 是唯一安全、可靠的方式——它会校验文件是否真来自上传临时目录,防止路径遍历或伪造文件攻击。用 copy($_FILES['audio']['tmp_name'], $dest) 或 file_get_contents($_FILES['audio']['tmp_name']) 是危险的,临时文件可能已被清理或被篡改。
典型操作流程:
- 检查
$_FILES['audio']['error'] === UPLOAD_ERR_OK - 用
pathinfo($_FILES['audio']['name'], PATHINFO_EXTENSION)提取扩展名,不要相信客户端传来的type字段(可伪造) - 白名单校验扩展名:
in_array(strtolower($ext), ['mp3', 'wav', 'ogg', 'm4a']) - 生成安全文件名(如
uniqid() . '.' . $ext),避免中文、空格、特殊字符 - 确保目标目录存在且 Web 服务器有写权限(如
chmod 755 uploads/)
音频文件需要额外做 MIME 类型二次校验
仅靠扩展名过滤不够。用户可把恶意脚本改成 xxx.mp3 上传。必须用 finfo_open() 检查真实类型:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $_FILES['audio']['tmp_name']);
finfo_close($finfo);
if (!in_array($mimeType, ['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/mp4'])) {
die('不支持的音频格式');
}
注意:mime_content_type() 已废弃;getimagesize() 只适用于图片;$_FILES['audio']['type'] 完全不可信,浏览器自填,可任意修改。
大音频文件上传要处理超时和分片(max_execution_time 和前端分片)
一个 50MB 的 WAV 文件上传可能耗时几十秒,PHP 默认 max_execution_time=30 会中断脚本,返回 500 错误,但客户端往往只看到空白页或网络错误。这时候不能只调大超时——更稳妥的是前端分片上传(如用 axios + Blob.slice()),后端按序合并。
如果坚持单次上传,至少同步调整这些值:
-
max_execution_time(php.ini 或set_time_limit(300)) -
max_input_time(处理输入数据的时间上限) - Nginx 用户还要加
client_max_body_size 50M和fastcgi_read_timeout 300
真正难处理的不是“怎么传”,而是传到一半断连、重复提交、并发覆盖——这些得靠唯一请求 ID、分片校验、服务端去重逻辑来兜底,不是改几个 ini 就能解决的。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











