.po、.mo文件对应的MIME类型是什么?PHP服务端如何校验其上传?
校验方案说明
首先要注意:你目前在用的$_FILES[$i]['type']是客户端提交的请求头参数,可被任意伪造,完全不具备安全校验意义,必须通过服务端读取文件内容检测真实类型。
1. PO/MO文件对应的标准MIME类型
.po(人工可读翻译文件):text/x-gettext-translation.mo(机器可读翻译文件):application/x-gettext-translation
部分低版本系统可能将mo识别为通用二进制流application/octet-stream,可实测后按需加入允许列表。
2. 可靠校验实现(基于PHP内置Finfo扩展)
PHP 5.3及以上版本默认内置Finfo扩展,可直接读取文件内容识别真实MIME类型,配合后缀双重校验即可覆盖绝大多数安全场景:
// 配置允许规则 $allowedMimes = [ 'text/x-gettext-translation', 'application/x-gettext-translation' ]; $allowedExts = ['po', 'mo']; // 读取上传文件信息 $tmpPath = $_FILES['upload_field']['tmp_name']; $originName = $_FILES['upload_field']['name']; // 第一步:校验文件后缀 $ext = strtolower(pathinfo($originName, PATHINFO_EXTENSION)); if (!in_array($ext, $allowedExts)) { echo "oh, please, no hacking here"; exit; } // 第二步:校验真实文件MIME $finfo = new Finfo(FILEINFO_MIME_TYPE); $realMime = $finfo->file($tmpPath); if (in_array($realMime, $allowedMimes)) { echo "ok"; // 后续文件处理逻辑 } else { echo "oh, please, no hacking here"; exit; }
3. 更高安全级别的补充校验
如果对安全性要求更高,可以针对文件特征做二次校验:
- po文件校验:po是纯文本格式,可检测内容是否包含
msgid ""这类gettext标准标识 - mo文件校验:mo是二进制格式,文件头有固定魔数,可通过读取前4个字节验证:
if ($ext === 'mo') { $f = fopen($tmpPath, 'rb'); $header = fread($f, 4); fclose($f); // mo文件魔数分大小端两种格式 if (!in_array(bin2hex($header), ['950412de', 'de120495'])) { echo "invalid .mo file"; exit; } }
额外安全建议
- 上传后的文件不要存储在web可直接访问的目录,优先存到项目根目录以外的路径
- 上传后重命名文件名,避免路径穿越、恶意覆盖原有文件的风险
- 给上传文件目录配置禁止执行PHP/ASP等脚本的权限,避免恶意脚本执行
内容的提问来源于stack exchange,提问作者creators
相关产品推荐
相关产品推荐

