桌面端音频上传正常,移动端返回octet-stream提示格式不符求排查
解决移动端音频上传MIME类型识别错误的问题
我完全懂你现在的困扰——桌面端传音频一切顺畅,换到手机上就老是跳格式错误提示,查了才发现MIME类型变成了octet-stream。这其实是移动端浏览器的常见问题:不少手机浏览器不会正确识别音频文件的MIME类型,反而把它当成通用的二进制流返回,直接绕开了你当前的校验逻辑。
问题根源
你现在的代码完全依赖$_FILES['audio']['type']判断文件类型,但这个值是客户端浏览器提供的,并不是文件的真实MIME类型。移动端浏览器经常会返回不准确的结果,比如把音频文件识别成application/octet-stream,导致你的格式校验直接触发错误。
修复方案
方案1:结合文件扩展名做双校验
既然客户端的MIME不可靠,我们可以同时检查文件扩展名,用双保险来判断是否为合法音频格式。
修改后的代码如下:
if (isset($_POST['submit_atrack'])) { $fileinfo = PATHINFO($_FILES["audio"]["name"]); $newFilename = $fileinfo['filename'] . uniqid($usr_idLogged) . "." . $fileinfo['extension']; $location = 'atracks/' . $newFilename; // 允许的MIME类型(兼容移动端返回的octet-stream) $allowedMimes = array('audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/mp3', 'application/octet-stream'); // 允许的文件扩展名 $allowedExtensions = array('mp3', 'ogg', 'wav', 'mpeg'); $tamanho_max = 500000000; //500 mb if (empty($_FILES['audio']['name'])) { $upload_empty = urlencode("empty"); header("Location:playlist?newtrack=" . $upload_empty . "&playlist=" . $selectedPlaylist); exit; } // 先校验扩展名,再结合MIME类型判断(给octet-stream开绿灯) $fileExt = strtolower($fileinfo['extension']); $isValidExt = in_array($fileExt, $allowedExtensions); $isValidMime = in_array($_FILES['audio']['type'], $allowedMimes); if (!$isValidExt || (!$isValidMime && $_FILES['audio']['type'] !== 'application/octet-stream')) { $upload_incorrectformat = urlencode("incorrectext"); header("Location:playlist?newtrack=" . $upload_incorrectformat . "&playlist=" . $selectedPlaylist); exit; } if ($_FILES['audio']['size'] >= $tamanho_max) { $upload_maxsize = urlencode("maxsizereached"); header("Location:playlist?newtrack=" . $upload_maxsize . "&playlist=" . $selectedPlaylist); exit; } // 先执行文件移动,再写入数据库(避免数据库存了路径但文件没传成功) if (move_uploaded_file($_FILES["audio"]["tmp_name"], $location)) { $atitle = mysqli_real_escape_string($connection, $_POST['atitle']); $atag = mysqli_real_escape_string($connection, $_POST['atag']); $atagcolor = mysqli_real_escape_string($connection, $_POST['atagcolor']); mysqli_query($connection,"INSERT INTO tbl_users_atrack (atrack_title, atrack_path, atrack_tag, atrack_tagColor, atrack_playlistId) VALUES ('$atitle', '$location', '$atag', '$atagcolor', '$selectedPlaylist')"); $upload_success = urlencode("success"); header("Location:playlist?newtrack=" . $upload_success . "&playlist=" . $selectedPlaylist); } else { // 处理文件移动失败的情况 $upload_error = urlencode("uploaderror"); header("Location:playlist?newtrack=" . $upload_error . "&playlist=" . $selectedPlaylist); } exit; }
方案2:用finfo检测真实文件类型(更安全)
如果想要更严谨的校验,推荐用PHP的finfo扩展读取文件的真实MIME类型——这个是从文件内容分析出来的,完全不受客户端返回值的影响,能彻底杜绝伪造文件类型的问题。
核心代码示例:
// 初始化finfo对象,用于读取文件真实MIME类型 $finfo = new finfo(FILEINFO_MIME_TYPE); // 获取上传文件的真实MIME类型 $realMimeType = $finfo->file($_FILES["audio"]["tmp_name"]); // 定义允许的真实音频MIME类型 $allowedRealMimes = array('audio/mpeg', 'audio/ogg', 'audio/wav'); // 替换原来的MIME校验逻辑 if (!in_array($realMimeType, $allowedRealMimes)) { $upload_incorrectformat = urlencode("incorrectext"); header("Location:playlist?newtrack=" . $upload_incorrectformat . "&playlist=" . $selectedPlaylist); exit; }
把这段逻辑替换你原来依赖$_FILES['audio']['type']的校验,就能彻底解决移动端的识别问题,同时提升上传的安全性。
额外小提示
- 确认服务器上
atracks目录的写入权限是否正常,避免出现文件移动失败的情况。 - 如果你用的是较老的PHP版本,
finfo可能需要手动在php.ini里开启,不过现在大部分服务器环境默认已经启用了。
内容的提问来源于stack exchange,提问作者Luann Sousa
相关产品推荐
相关产品推荐

