必须先调用getimagesize()校验图片有效性并获取尺寸,否则imagecreatefromjpeg()等函数失败返回false会导致后续imagecopyresampled()崩溃;需检查返回值、处理透明通道、创建目录、按场景设置JPEG质量参数,并分版本处理WebP支持。

PHP 上传图片后生成缩略图,getimagesize() 必须先调用
不检查原始尺寸就硬缩放,轻则白图黑边,重则 imagecopyresampled() 崩溃报 Warning: imagecopyresampled(): supplied argument is not a valid Image resource。原因很简单:你传了个假资源进去——比如 imagecreatefromjpeg() 失败返回 false,但没拦截,直接往下用了。
-
getimagesize()不仅返回宽高,还会校验文件是不是真图片(魔数检测),比单纯看后缀靠谱得多 - 如果返回
false,立刻终止流程,别碰imagecreatefrom*系列函数 - 注意它对 WebP 支持依赖 PHP 版本(7.4+ 原生支持,低版本需 GD 扩展编译时开启)
用 imagecopyresampled() 而不是 imagecopyresized()
后者只做最近邻插值,小图拉大或大图压小都会糊成马赛克;前者用双线性重采样,细节保留好很多。但代价是 CPU 占用略高——对单次上传影响可忽略,别为了省几毫秒牺牲清晰度。
- 目标尺寸必须是正整数,
0或负数会导致函数静默失败,返回false - 源图像坐标(
$src_x,$src_y)通常为0,但要做裁切时就得算清楚,别直接抄示例里的0, 0 - GD 默认不支持透明通道保存到 JPEG,PNG/WebP 源图缩成 JPEG 会丢 alpha,背景变黑——得手动填底色或换输出格式
保存缩略图前,imagejpeg() 的质量参数别写死
写死 imagejpeg($thumb, $path, 95) 很常见,但对手机拍的原图(动辄 3–5MB)意义不大,体积降不下来;对图标类小图反而可能把噪点放大。建议按场景分级:
- 网页展示图:75–82(肉眼难辨差异,体积减少 40%+)
- 用户头像/商品主图:85–90(兼顾清晰与加载速度)
- 打印级预览:92+(仅限极少数场景,慎用)
- 务必加
!is_dir(dirname($path)) && mkdir(dirname($path), 0755, true),否则路径不存在直接报错
WebP 格式支持要分 PHP 版本处理
PHP 7.4+ 可直接用 imagewebp();低于这个版本,要么升级,要么用 exec('cwebp -q 80 '.$src.' -o '.$dst) 调系统命令(需服务器装 cwebp)。别试图用 GD 强转——旧 GD 根本不认 WebP 文件头。
立即学习“PHP免费学习笔记(深入)”;
- 判断是否支持:
function_exists('imagewebp'),不是看extension_loaded('gd') - WebP 缩略图保存失败时,
error_get_last()返回的错误信息里常含failed to write webp,不是权限问题就是 GD 不支持 - 浏览器兼容性不用操心,现代浏览器都支持;但微信内嵌浏览器(尤其旧版)可能回退到 JPEG,留个备选逻辑更稳
缩略图逻辑看着简单,真正卡住人的永远是那几个“应该没问题”的环节:没校验原始文件、没处理透明通道、路径没创建、质量参数一刀切。这些地方一漏,调试时日志里找不到线索,只能靠 print_r(getimagesize()) 一行行试。











