为什么imagecreatefromjpeg函数无法处理后缀为.jpg的图片文件?
问题根因
- 图片资源创建无校验
代码没有判断imagecreatefromjpeg的返回值是否有效,部分后缀为.jpg的文件存在格式异常(比如实际为webp等其他格式改后缀、渐进式jpg、文件头损坏)时,会直接返回false,后续执行imagesx/imagesy会抛出错误,若你开启了错误抑制就会出现无报错、无日志、无输出的情况。 - 分支逻辑缺少大括号
目标扩展名的判断分支没有加花括号,只有$ext = 'jpg'属于if判断的执行逻辑,后续的$dest重写语句会无条件执行,部分场景下会导致目标路径不符合预期。 - 缺少基础权限校验
代码没有校验源文件是否存在、是否可读,目标目录是否有写入权限,也没有处理jpg的exif旋转属性,会导致手机拍摄的jpg生成缩略图后方向错误。
修复后的完整代码
function create_thumb($src,$dest,$desired_width = false, $desired_height = false){ // 基础参数校验 if (!$desired_height&&!$desired_width) return false; if (!file_exists($src) || !is_readable($src)) return false; $fparts = pathinfo($src); $ext = strtolower($fparts['extension']); if (!in_array($ext,array('gif','jpg','png','jpeg'))) return false; // 创建图片资源 if ($ext == 'gif') $resource = imagecreatefromgif($src); else if ($ext == 'png') $resource = imagecreatefrompng($src); else if ($ext == 'jpg' || $ext == 'jpeg') $resource = imagecreatefromjpeg($src); // 校验资源是否创建成功 if (!$resource) { // 兼容处理格式异常的jpg文件 $resource = imagecreatefromstring(file_get_contents($src)); if (!$resource) return false; } $width = imagesx($resource); $height = imagesy($resource); // 处理jpg exif旋转 if (($ext == 'jpg' || $ext == 'jpeg') && function_exists('exif_read_data')) { $exif = exif_read_data($src); if (!empty($exif['Orientation'])) { switch ($exif['Orientation']) { case 3: $resource = imagerotate($resource, 180, 0); break; case 6: $resource = imagerotate($resource, -90, 0); list($width, $height) = [$height, $width]; break; case 8: $resource = imagerotate($resource, 90, 0); list($width, $height) = [$height, $width]; break; } } } if(!$desired_height) $desired_height = floor($height*($desired_width/$width)); if(!$desired_width) $desired_width = floor($width*($desired_height/$height)); $virtual_image = imagecreatetruecolor($desired_width,$desired_height); // 处理透明背景 if ($ext == 'gif' || $ext == 'png') { imagealphablending($virtual_image, false); imagesavealpha($virtual_image, true); $transparent = imagecolorallocatealpha($virtual_image, 255, 255, 255, 127); imagefilledrectangle($virtual_image, 0, 0, $desired_width, $desired_height, $transparent); } imagecopyresampled($virtual_image,$resource,0,0,0,0,$desired_width,$desired_height,$width,$height); $fparts = pathinfo($dest); $ext = strtolower($fparts['extension']); // 补全目标扩展名逻辑的大括号 if (!in_array($ext,array('gif','jpg','png','jpeg'))) { $ext = 'jpg'; $dest = $fparts['dirname'].'/'.$fparts['filename'].'.'.$ext; } if ($ext == 'gif') imagegif($virtual_image,$dest); else if ($ext == 'png') imagepng($virtual_image,$dest,1); else if ($ext == 'jpg' || $ext == 'jpeg') imagejpeg($virtual_image,$dest,72); // 释放内存 imagedestroy($resource); imagedestroy($virtual_image); return array( 'width' => $width, 'height' => $height, 'new_width' => $desired_width, 'new_height'=> $desired_height, 'dest' => $dest ); }
优化说明
- 新增了源文件存在性、可读性校验,避免无效路径执行
- 新增了图片资源创建失败的兼容逻辑,可处理大部分格式异常的jpg文件
- 新增了jpg exif旋转处理,解决手机拍摄图片方向错误的问题
- 新增了png/gif透明背景支持
- 修复了目标扩展名逻辑的大括号问题,避免路径异常
- 新增了内存释放逻辑,避免长时间运行内存溢出
- 替换
imagecopyresized为imagecopyresampled,生成的缩略图质量更高
内容的提问来源于stack exchange,提问作者RoX。
相关产品推荐
相关产品推荐

