upload_err_ini_size 是 php 层拦截,需调大 php.ini 中 upload_max_filesize 和 post_max_size(后者≥前者),并重启 web 服务;nginx 还需检查 client_max_body_size,表单必须含 enctype="multipart/form-data"。

ThinkPHP 上传失败提示 UPLOAD_ERR_INI_SIZE 怎么办
这是 PHP 层面拦截的典型信号,不是 ThinkPHP 自己报的错。框架根本没机会处理——文件在进到 $_FILES 之前就被 php.ini 拦下了。必须先确认 upload_max_filesize 和 post_max_size 是否足够大,且 post_max_size ≥ upload_max_filesize(否则后者无效)。
常见错误现象:$_FILES 为空、$_FILES['xxx']['error'] === 1、日志里看不到 ThinkPHP 的上传逻辑执行痕迹。
-
upload_max_filesize控制单个文件上限(如20M) -
post_max_size控制整个 POST 请求体上限(含文件+表单字段,建议设为25M或更高) - 改完记得重启 Web 服务(
php-fpm或 Apache),仅重载配置不生效
ThinkPHP 6 的 FileValidate 配置为什么没生效
框架级验证是“第二道关”,只在 PHP 允许上传的前提下才起作用。它不会覆盖 php.ini 限制,但能提前拦截不符合业务规则的文件(比如类型、尺寸、后缀)。如果 FileValidate 的 size 参数设成 10 * 1024 * 1024,而 php.ini 是 2M,那用户连触发这个验证的机会都没有。
使用场景:前端传了 5MB 图片,php.ini 允许,但业务只要 ≤ 2MB;这时 FileValidate 才真正介入。
- 验证参数写在控制器方法的
validate规则里,例如:['size' => '2097152'](单位字节) - 注意单位:ThinkPHP 不认
'2M'这种字符串写法,必须是整数 - 若用
validate方法手动调用,需确保传入的是$_FILES数组原值,不是经过request()->file()封装后的对象
ThinkPHP 5.1 中 Request::file() 返回 null 的真实原因
除了 php.ini 限制,还有两个隐蔽原因常被忽略:表单 enctype 缺失,或 Nginx 配置里禁用了文件上传。
常见错误现象:前端明明选了文件、提交了表单,但 Request::file('avatar') 始终返回 null,$_FILES 也为空。
- 检查 HTML 表单是否写了
enctype="multipart/form-data"(没有这句,浏览器根本不会发文件) - Nginx 用户重点查
client_max_body_size,它和php.ini是并列限制,任一超限都会静默丢弃请求体 - ThinkPHP 5.1 默认不自动解析
$_FILES到Request::file(),需确认是否启用了file参数绑定(通常默认开启,但自定义 Request 类时可能被覆盖)
上传路径写成 ./runtime/upload 为什么总失败
相对路径在 CLI、FPM、Swoole 等不同运行环境下基准目录不同,./ 很可能指向 /var/www 或 /tmp,而非项目根目录。ThinkPHP 内部用的是绝对路径拼接,直接写相对路径等于把问题交给运行时猜。
性能影响不大,但兼容性极差——本地开发可能正常,上生产就 500。
- 统一用
app()->getRuntimePath() . 'upload/'或Env::get('root_path') . 'public/uploads/' - 确保目标目录存在且 Web 进程有写权限(
chown www-data:www-data或对应用户) - 别把上传目录放在
public/下又不加.htaccess或 Nginxlocation限制,否则容易被直接下载源文件
事情说清了就结束。最常漏掉的是 Nginx 的 client_max_body_size 和表单 enctype,这两个和 php.ini 一起构成三重闸门,少关一道都可能让上传卡在黑盒里。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











