thinkphp 8.0 文件上传需用 request()->file() 获取文件,配合 validate() 进行扩展名与 mime 类型双重校验,再调用 move() 保存;表单必须设 enctype="multipart/form-data",上传目录须置于 public/ 下并禁用 php 执行权限,同时同步调大 nginx 与 php 的上传限制。

ThinkPHP 8.0 实现文件上传需绕过旧版 Upload 类,改用 request()->file() + validate + move 的链式调用方式,同时必须校验 MIME 类型而非仅后缀名,否则攻击者可伪造 .jpg 后缀上传 WebShell。
创建安全上传表单
在视图中写表单时,【enctype="multipart/form-data"不可省略】,否则 $_FILES 为空,所有后续逻辑失效。
使用 ThinkPHP URL 助手生成 action 地址:<form action="%7B:url('upload')%7D" method="post" enctype="multipart/form-data"></form>
添加 file input 并设 name="avatar"(后端需匹配此名称):<input type="file" name="avatar" accept="image/*" required>
accept 属性仅前端提示,不构成安全限制,但能减少用户误选非图片文件。
控制器中完成校验与保存
在控制器方法里,先获取文件对象:
$file = request()->file('avatar');
立即执行白名单校验:扩展名 + MIME 类型双重验证,缺一不可。仅验后缀可被 Content-Type 伪造绕过:
$info = $file->validate(['size'=>2097152, 'ext'=>'jpg,png,gif,webp', 'mime'=>'image/jpeg,image/png,image/gif,image/webp'])->move('uploads');
move() 默认按日期生成子目录(如 uploads/2026/07/22/),避免单目录海量文件性能下降;若要自定义路径,传入第二个参数:move('uploads/user_avatar/', 'avatar_'.time().mt_rand(1000,9999).'.png')。
校验失败时 $info 为 false,调用 $file->getError() 可得具体原因,如“上传文件大小超过限制”或“非法图像文件”。
配置上传目录权限与位置
第一步:在 public/ 目录下新建 uploads 文件夹(【绝不能放在 application/ 或 config/ 等敏感目录下】)。
第二步:确保 Web 服务器用户(如 www-data 或 nginx)对该目录有写权限。Linux 下执行:chmod -R 755 public/uploads && chown -R www-data:www-data public/uploads。
第三步:禁止直接通过 URL 访问上传文件的原始路径。在 Nginx 配置中添加 location 规则屏蔽 PHP 执行:
location ^~ /public/uploads/ {<br> deny all;<br>}
这一步不做,攻击者上传 .php 文件后可通过 http://site.com/public/uploads/shell.php 直接触发执行。
处理大文件上传报 413 错误
方法一:改 Nginx 配置(必须写在 server 块内)
① 编辑站点 conf 文件,在 server { } 第一行插入:client_max_body_size 200m;
② 运行 nginx -t && nginx -s reload 生效,【不重载等于没改】。
方法二:同步调大 PHP 限制
① 找到真实生效的 php.ini(访问 info.php 查 Loaded Configuration File)
② 修改两项值并保持一致:upload_max_filesize = 200M 和 post_max_size = 200M
③ 重启 PHP-FPM:systemctl restart php8.5-fpm(版本号按实际调整)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











