thinkphp文件上传核心是前端表单设enctype="multipart/form-data"、name与后端一致、后端用request()->file()接收并validate校验后move到public/uploads等可访问目录,同时检查php和nginx上传限制。

ThinkPHP 文件上传到本地服务器,核心是让文件从浏览器正确提交、被框架接收、验证后存入指定目录,并确保能安全访问。关键不在“能不能”,而在“怎么配得稳、传得准、存得对”。
前端表单必须带对编码类型
这是最常被忽略却直接导致 $_FILES 为空 的原因。
- form 标签一定要写 enctype="multipart/form-data",缺了这句,PHP 根本收不到任何文件数据
- input type="file" 的 name 属性(比如
name="avatar")必须和后端调用的字段名完全一致,例如request()->file('avatar') - 如果用 Ajax 提交,不能发 JSON;要用 FormData + 原生 fetch 或 XMLHttpRequest,且不要手动设置 Content-Type,让浏览器自动设为 multipart
后端接收与保存路径要明确可控
ThinkPHP 默认把文件存到 runtime/storage/ 这类非公开目录,前端无法直接访问。实际项目中更推荐存到 public/uploads/ 下。
- 先在
public/目录下手动创建uploads文件夹,并确保 Web 服务器(如 Nginx/Apache)有写权限 - 控制器里用
request()->file('xxx')获取文件对象,再调用move('uploads')或move(public_path() . '/uploads') - 不要依赖默认路径;
$info->getSaveName()返回的是相对路径(如20260921/abc123.jpg),拼成完整 URL 就是/uploads/20260921/abc123.jpg
必须加验证,否则等于敞开大门
仅靠后缀名判断类型极不安全,ThinkPHP 支持多层校验,建议全开。
- 用
validate(['ext' => 'jpg,png,gif,jpeg', 'size' => 2048000])限制扩展名和大小(单位字节) - 开启 MIME 类型检测:ThinkPHP 6+ 的
putFile()或启用checkMime => true可识别真实文件类型,防伪装木马 - 重命名建议用
rule('date')或rule('uniqid'),避免覆盖和猜测路径
别忘了服务器和 PHP 层的硬性限制
框架报错前,PHP 或 Nginx 可能已静默拦截上传请求。
- 检查
php.ini:确认file_uploads = On,upload_max_filesize和post_max_size足够大(后者 ≥ 前者) - Nginx 需配置
client_max_body_size 10M;,位置在 http/server/location 块中 - 调试时先
dump($_FILES)看原始数据,比只看 ThinkPHP 返回值更可靠
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











