直接修改 upload_mimes 过滤器可服务端强制控制 wordpress 后台上传文件类型白名单,需通过 add_filter('upload_mimes', 'callback') 返回精确的扩展名-mime 映射数组,忽略浏览器提供的 $_files['type'],并确保 mime 符合 iana 标准。

直接改 upload_mimes 过滤器就能控制后台上传类型
WordPress 后台媒体上传的文件类型白名单,由 upload_mimes 过滤器决定。它不依赖前端 JS 或表单隐藏字段,而是服务端强制校验——只要没出现在返回的数组里,哪怕绕过浏览器限制强行 POST,也会被 wp_handle_upload() 拒绝并报错 "Sorry, this file type is not permitted for security reasons."。
常见错误是只加 MIME 类型却忽略扩展名映射逻辑,或误用 $_FILES['type'] 做判断(该值由浏览器提供,不可信)。
- 必须通过
add_filter('upload_mimes', 'your_function')注册回调函数 - 函数接收一个关联数组
$existing_mimes,键是扩展名(如'pdf'),值是 MIME 类型(如'application/pdf') - 添加用赋值:
$existing_mimes['zip'] = 'application/zip'; - 禁止用
unset():unset($existing_mimes['exe']); - 修改后需刷新后台「媒体 → 添加新文件」页面才能看到更新后的提示文字(如“最大上传文件大小:2MB”下方会隐含生效范围)
upload_mimes 回调里 MIME 类型写错会导致上传失败
扩展名和 MIME 类型必须匹配真实文件内容,否则部分服务器(尤其是启用了 mod_security 或严格 fileinfo 检查的环境)会拒绝上传。例如:$existing_mimes['woff'] = 'application/font-woff'; 是旧标准,现在应写成 'font/woff';'rar' 对应的 MIME 类型不是 'application/rar'(已废弃),而应是 'application/vnd.rar'。
推荐优先查 IANA 官方注册表或用 PHP 的 finfo_file() 实测确认,而不是凭经验硬写。
- 图片类基本安全:
$existing_mimes['webp'] = 'image/webp'; - 字体类注意区分:
'woff'→'font/woff','woff2'→'font/woff2' - 归档类推荐标准写法:
$existing_mimes['zip'] = 'application/zip';,$existing_mimes['7z'] = 'application/x-7z-compressed'; - 避免使用模糊类型如
'application/octet-stream',它可能被 WordPress 自动过滤掉
仅允许上传 PDF 和 SVG,禁止所有其他类型怎么实现
这不是简单删减,而是彻底重置白名单。直接覆盖 $existing_mimes 数组比逐个 unset() 更可靠,尤其当主题或插件已添加了额外类型时。
以下代码放在主题 functions.php 中即可生效:
add_filter('upload_mimes', 'restrict_to_pdf_and_svg');
function restrict_to_pdf_and_svg($existing_mimes) {
return [
'pdf' => 'application/pdf',
'svg' => 'image/svg+xml',
'svgz' => 'image/svg+xml'
];
}
注意:svgz 是压缩版 SVG,MIME 类型仍为 'image/svg+xml';如果还要支持带查询参数的 SVG URL(如 icon.svg?ver=1.0),需额外处理 wp_check_filetype() 的解析逻辑,但绝大多数场景不需要。
这个方案不兼容「上传后自动转 WebP」等依赖原图类型的插件,启用前请确认业务无此类依赖。
为什么加了代码还是能上传 .exe?
大概率是缓存或钩子执行时机问题。WordPress 在加载过程中可能多次运行 upload_mimes 过滤器,后注册的回调会覆盖先注册的——如果你的主题、子主题、插件都挂了同名过滤器,只有最后一个生效。
检查方法:在回调函数开头加 error_log('upload_mimes triggered');,上传时看 PHP 错误日志是否真被调用;再用 var_dump($existing_mimes); 确认传入的数组是否已含 'exe'。
- 确保代码在
functions.php的最外层作用域,不要包在某个条件判断或函数内部 - 避免子主题未正确加载父主题的
functions.php,导致你的修改未执行 - 某些安全插件(如 Wordfence、iThemes Security)会主动重写
upload_mimes,此时需在其设置中关闭「阻止可执行文件上传」选项,或改用插件提供的 API - Apache + mod_php 环境下,
.htaccess里的php_value设置若包含disable_functions,可能导致ini_set()失效,间接影响依赖它的上传逻辑
真正起效的永远是最终返回的那个数组,而不是你写了什么——调试时盯住返回值,别只看代码行。











