PHP实现图片压缩后添加水印报错:图片无法显示如何解决
代码问题排查&修复方案
核心错误点
- 错误将GD内存资源当作文件路径使用
调整完尺寸得到的$dest_image是GD库生成的内存图像资源,不是本地JPG文件的路径。你后续直接将其传入imagecreatefromjpeg()和getimagesize()两个需要读取本地文件的函数,直接触发代码报错,输出的错误文本破坏了图片二进制流结构,导致图片无法正常显示。 - PNG水印透明通道丢失风险
直接用imagecopy()合并PNG水印会丢失透明背景,需要额外开启alpha通道保存设置。 - 缺少基础错误校验
没有判断原图、水印文件是否存在,也没有捕获GD函数的执行错误,一旦文件读取失败就会产生报错文本,同样会导致图片无法正常显示。 - 存在路径遍历安全风险
直接使用$_GET['slika']传入的路径作为读取目标,攻击者可构造特殊路径读取服务端敏感文件。
修复后完整代码
<?php // 先关闭错误输出,避免报错文本破坏图片流 ini_set('display_errors', 0); if(isset($_GET['slika'])) { $slika = $_GET['slika']; // 可选:增加路径校验,避免路径遍历风险,比如只允许读取指定目录下的文件 // 示例:if(strpos(realpath($slika), '/path/to/allowed/image/dir/') !== 0) die('非法路径'); } else { $slika = "ni_posterja.jpg"; } // 校验原图是否存在且可读 if(!file_exists($slika) || !is_readable($slika)) { $source_image = imagecreatefromjpeg("ni_posterja.jpg"); } else { $source_image = imagecreatefromjpeg($slika); } if(!$source_image) die('原图加载失败'); $source_imagex = imagesx($source_image); $source_imagey = imagesy($source_image); $dest_imagex = 500; $dest_imagey = 300; $dest_image = imagecreatetruecolor($dest_imagex, $dest_imagey); imagecopyresampled($dest_image, $source_image, 0, 0, 0, 0, $dest_imagex, $dest_imagey, $source_imagex, $source_imagey); // 销毁不需要的原图资源 imagedestroy($source_image); // 校验水印文件是否存在 $watermark_path = '../nastavitve/slike/logo_zascita.png'; if(!file_exists($watermark_path) || !is_readable($watermark_path)) { // 水印不存在直接输出调整后的图 header("Content-Type: image/jpeg"); imagejpeg($dest_image,NULL,60); imagedestroy($dest_image); exit; } $my_watermark = imagecreatefrompng($watermark_path); if(!$my_watermark) { header("Content-Type: image/jpeg"); imagejpeg($dest_image,NULL,60); imagedestroy($dest_image); exit; } $watermark_width = imagesx($my_watermark); $watermark_height = imagesy($my_watermark); // 直接在调整好尺寸的$dest_image上加水印,不需要再重新读文件 $wm_x = $dest_imagex - $watermark_width - 20; $wm_y = $dest_imagey - $watermark_height - 20; // 保留PNG水印的透明通道 imagealphablending($dest_image, true); imagesavealpha($dest_image, true); imagecopy($dest_image, $my_watermark, $wm_x, $wm_y, 0, 0, $watermark_width, $watermark_height); // 销毁水印资源 imagedestroy($my_watermark); // 输出最终图片 header("Content-Type: image/jpeg"); imagejpeg($dest_image,NULL,60); imagedestroy($dest_image); ?>
内容的提问来源于stack exchange,提问作者Jure
相关产品推荐
相关产品推荐

