根本原因是php未正确声明content-type且存在前置输出;必须在imagejpeg()前调用header('content-type: image/jpeg'),且确保无空格、bom、echo等任何前置输出,文件须为utf-8无bom编码。

为什么直接用 imagejpeg() 输出验证码会失败
常见现象是浏览器显示一片空白,或者弹出下载对话框,而不是正常显示图片。根本原因是 PHP 脚本没有正确声明输出内容类型,浏览器不知道接收到的是 JPG 图片,于是按文本或未知类型处理。
必须在调用 imagejpeg() 前,用 header('Content-Type: image/jpeg') 明确告知浏览器 MIME 类型;且该 header() 不能有任何前置输出(包括空格、BOM、echo、print),否则会报 “Headers already sent” 错误。
- 确保 PHP 文件保存为 UTF-8 无 BOM 格式
- 文件开头不能有空行或
<?php前的任何字符 - 不要在
header()前做任何输出(含error_reporting(E_ALL)触发的警告)
生成带干扰线和扭曲字母的 JPG 验证码
PHP GD 库支持直接绘制文字和线条,但默认字体不支持中文,且纯 imagestring() 画出的字母太规整、易被 OCR 识别。需手动控制坐标、旋转和噪点。
关键操作顺序:创建画布 → 填充背景色 → 绘制干扰线 → 逐个写入随机字母(带小角度旋转)→ 添加少量噪点 → 输出 JPG。
session_start(); $width = 120; $height = 40; $image = imagecreatetruecolor($width, $height); $bg = imagecolorallocate($image, 245, 245, 245); imagefill($image, 0, 0, $bg); // 干扰线 for ($i = 0; $i <p>注意:<code>imagettftext()</code> 依赖系统中存在 TrueType 字体(如 <code>arial.ttf</code>),Linux 下路径常为 <code>/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf</code>,Windows 下可能是 <code>C:/Windows/Fonts/arial.ttf</code>;路径错误会导致文字不显示且无报错。</p> <h3>浏览器缓存导致验证码不刷新</h3> <p>用户点击“换一张”时,图片 URL 没变(比如固定为 <code>/captcha.php</code>),浏览器直接从缓存取旧图,看起来验证码没变化。</p> <p>解决方法是在 img 标签的 src 后加时间戳或随机参数,强制绕过缓存:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站"><img src="https://img.php.cn/upload/skill/000/000/081/179040786932301.jpg" alt="btpanel phpsite 宝塔面板PHP网站" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站" class="overflowclass">btpanel phpsite 宝塔面板PHP网站</a> <p class="overflowclass">宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理</p> </div> <a rel="nofollow" href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <pre class="brush:php;toolbar:false;">@@##@@" alt="验证码">
或者前端用 JS 点击时动态更新:
document.getElementById('captcha-img').src = 'captcha.php?r=' + Math.random();
后端无需改逻辑,但务必确保 captcha.php 不输出任何额外字符(包括末尾空行),否则 JPG 数据流会被破坏,显示为损坏图片。
GD 扩展未启用或不支持 JPG
运行时出现 Call to undefined function imagejpeg(),说明 PHP 编译时未启用 GD 扩展,或启用了但禁用了 JPG 支持。
检查方式:
- 运行
php -m | grep gd看是否列出gd - 执行
php -r "var_dump(gd_info());",确认jpeg字段为true
常见修复路径:
- Ubuntu/Debian:
sudo apt install php-gd,然后重启 web 服务 - CentOS/RHEL:
sudo yum install php-gd或dnf install php-gd - Windows:取消
php.ini中;extension=gd的分号,并确认extension=php_gd2.dll存在且路径正确
如果服务器不允许开启 GD(如某些共享主机),只能改用 base64 内嵌 PNG(用 imagepng() + base64_encode()),但 JPG 在同等质量下体积更小,更适合验证码场景。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










