当前位置:首页 > 百科

thinkphp5图片上传

ThinkPHP5 里处理图片上传,图片核心就三步:接收文件、上传验证规则、图片移动文件。上传别把这事想复杂了,图片框架已经把大部分脏活累活干完了。上传

先看最基础的图片写法。表单提交过来,上传控制器里这样接:

$file = request()->file('image'); if ($file) {  $info = $file->move(ROOT_PATH . 'public/uploads'); if ($info) {  echo $info->getSaveName(); } }

就这么几行,图片图片已经躺在 public/uploads 里了。上传move 方法返回的图片是文件对象,getSaveName 拿到的上传是自动生成的随机文件名,带日期目录那种,图片比如 20240515/3f2a8b1c.png。上传这设计挺省心,图片不用自己拼路径。

但实际项目里没人敢这么裸奔。你得管管文件类型和大小。TP5 的验证器能直接用在文件上,写法很直观:

$validate = \think\Validate::make([ 'image' => 'require|image|fileSize:2097152|fileExt:jpg,png,gif' ]); if (!$validate->check(['image' => $file])) {  return json(['code' => 0, 'msg' => $validate->getError()]); }

这里我限了 2MB 以内,只允许 jpg、png、gif。有个坑得提醒你:fileExt 校验的是扩展名,不是真实文件类型。要是较真,得用 finfo_open 去读 MIME。不过大多数后台管理系统,扩展名加文件头检查就够用了。

接下来是路径问题。很多人直接把图片存到 public 下就完事,结果服务器一配,发现访问不了。记得 uploads 目录得给写权限。Linux 下 chmod -R 755 uploads 是常规操作。但别给 777,除非你想被挂马。

再说说重命名。TP5 默认用 uniqid 生成文件名,这有个隐患——并发高的时候可能撞名。我习惯自己传规则:

$info = $file->move(ROOT_PATH . 'public/uploads', true, false, function($file) {  return md5($file->getInfo('name') . microtime()) . '.' . $file->getExtension(); });

第三个参数 false 表示不保留原文件名,闭包里的逻辑完全自己控制。用 md5 加微秒,基本不会重复。你也可以用时间戳加随机数,看个人喜好。

有个细节容易忽略——图片上传成功后的路径拼接。拿到的 getSaveName 是相对 uploads 的路径,前端要显示得拼上域名。我习惯在配置里加个 upload_url,统一处理:

$fullPath = config('upload_url') . '/' . $info->getSaveName();

这样换服务器改配置就行,代码不用动。

多图上传是另一个场景。TP5 里 name 用数组就行:

// HTML 里 name="images[]" $files = request()->file('images'); foreach ($files as $file) {  // 逐个处理,逻辑和单图一样 }

批量处理时记得每个文件单独验证,别只查第一个。我就吃过这亏,用户传了两个文件,一个合法一个带毒,全放进去了。

最后说下异常处理。move 方法失败时返回 false,但具体原因得看 getError。有些人图省事不查错误信息,结果图片传不上去都不知道是权限问题还是大小超限。加个日志记录会省很多排查时间:

if (!$info) {  \think\facade\Log::error($file->getError()); return json(['code' => 0, 'msg' => '上传失败']); }

图片上传这事,看着简单,实际坑不少。但把验证规则、路径管理、错误处理这三块理清楚,基本就能应付绝大多数场景。别指望框架帮你全做完,该写的判断一个都省不了。

分享到: