ThinkPHP文件上传需三层协同配置:PHP层设upload_max_filesize和post_max_size,Web服务器层配client_max_body_size(Nginx)或LimitRequestBody(Apache),框架层用validate()校验size(字节)和ext(小写白名单),缺一不可。

ThinkPHP 文件上传的白名单和大小限制必须分三层配置:PHP 底层、Web 服务器(Nginx/Apache)、框架应用层。只设其中一层,上传仍会失败或存在安全隐患。
一、PHP 层:放开底层解析上限
这是第一道关卡,不调大就根本进不了 ThinkPHP。修改 php.ini:
-
upload_max_filesize:单文件最大体积,例如设为
upload_max_filesize = 20M -
post_max_size:整个 POST 请求体上限,必须 ≥ upload_max_filesize,建议多留 5–10MB,例如
post_max_size = 25M -
max_file_uploads(可选):单次请求最多上传几个文件,默认 20,如需批量上传更多,可设为
max_file_uploads = 50
改完后必须重启 PHP 服务(如 systemctl restart php-fpm),并用 phpinfo() 页面确认值已生效。
二、Web 服务器层:防止 413 错误
即使 PHP 放开了,Nginx 或 Apache 也会在请求抵达前拦截超限请求体,直接返回 413 Request Entity Too Large,且 PHP 日志里无记录。
-
Nginx:在对应站点的
server块内添加:client_max_body_size 25m;(注意单位是m,不是M,且别写在http全局块) -
Apache:检查虚拟主机配置或项目根目录下的
.htaccess,确保没有过小的LimitRequestBody;如有,改为LimitRequestBody 26214400(即 25MB),或直接注释掉
修改后需验证并重载:nginx -t && nginx -s reload 或 apachectl configtest && systemctl reload apache2。
三、ThinkPHP 层:设置白名单与大小校验
这一层是应用逻辑校验,仅在文件成功上传到临时目录后才执行,用于细化业务规则,必须显式调用才生效。
-
大小限制:单位是字节,不能写
'size' => '2M'或'fileSize' => '2048K',会静默失效。
正确写法:'size' => 2097152(2MB),或用计算式2 * 1024 * 1024 -
白名单扩展名:必须全小写、不含点、无空格,例如
'ext' => ['jpg', 'png', 'pdf', 'xlsx']
若写成['JPG', 'PNG']或['.jpg'],校验会失败 -
调用方式:必须对
think\File对象调用validate()方法,例如:$file->validate(['size' => 2097152, 'ext' => ['jpg','png']])->move('uploads');
注意:该层校验无法拦截上传过程本身,仅作“最后一道防线”。如果用户上传了 100MB 文件,而 PHP 或 Nginx 已在解析阶段拒绝,validate() 根本不会运行。
额外安全建议
仅靠扩展名白名单易被绕过(如上传 shell.php.jpg),生产环境务必补充:
- 用
finfo_open(FILEINFO_MIME_TYPE)读取真实 MIME 类型,拒绝text/php、application/x-php等高危类型 - 上传后重命名文件,剥离原始文件名,用
uniqid() . '.' . $safeExt生成新名 - 上传目录不要放在
public/下,推荐移到runtime/uploads或storage/uploads,并通过 Web 服务器配置禁止脚本执行
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











