PHP生成验证码时Content-Type头必须设为image/png;不设或设错会导致浏览器直接下载文件、显示乱码或被前端异常处理。

PHP生成验证码时Content-Type头必须设为image/png
不设或设错Content-Type会导致浏览器直接下载文件、显示乱码,或被前端header('Content-Type: image/png');,或误写成
text/html、application/octet-stream。
实际使用中,只要输出图像(无论imagepng()、imagejpeg()还是imagegif()),就必须匹配对应MIME类型:
-
imagepng()→header('Content-Type: image/png'); -
imagejpeg()→header('Content-Type: image/jpeg'); -
imagegif()→header('Content-Type: image/gif');
注意:Header必须在任何输出(包括空格、BOM、echo)之前调用,否则会报Warning: Cannot modify header information。
字母验证码里避免混淆字符(如0/O, 1/l/I)
用户看不清、输错是验证码体验差的主因。PHP生成随机字符串时,不能简单用range('A','Z') + range('0','9')拼接全集,因为0和O、1和l、I在多数字体下几乎无法区分。
立即学习“PHP免费学习笔记(深入)”;
推荐做法是显式定义安全字符集:
- 去掉易混字符:
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; - 用
str_shuffle()+substr()取值,比array_rand()更可控 - 若需大小写混合,确保小写
l、o也不包含在内
别依赖字体加粗或倾斜来“增强可读性”——移动端或低分辨率屏上效果极不可靠。
session_start()必须在header()前且无输出
验证码值通常存入$_SESSION供后续校验,但session_start()本身会尝试发送Set-Cookie头。一旦前面有空格、UTF-8 BOM或echo,就会触发headers already sent警告,导致图像无法渲染。
检查点:
- PHP文件用UTF-8无BOM编码保存(编辑器可设)
- 文件开头**不能有任何字符**,包括
<?php前的空行或空格 - 不要在
session_start()后做var_dump()、print_r()等调试输出 - 如果项目已启用
output_buffering,虽能掩盖问题,但会掩盖真实流程缺陷,不建议依赖
GD库未启用或缺少字体时图像渲染失败
调用imagettftext()画文字却只看到空白图?大概率是GD扩展没开,或指定的字体路径不存在/权限不足/格式不支持。
快速验证方式:
- 执行
php -m | grep gd确认GD已加载 - 用
extension_loaded('gd')在脚本中判断,失败则die('GD not available'); - 字体路径必须是服务器绝对路径,
__DIR__ . '/font/arial.ttf'比'./font/arial.ttf'更可靠 - Linux下常见问题:.ttf文件权限为644,但Web用户(如www-data)无读取权
没有字体时,可用imagestring()兜底,但字形丑、难辨识,仅作临时调试用。



















