PHP getimagesize()在HTTPS下触发Apache超时,HTTP下正常
解决PHP getimagesize()在HTTPS环境下超时的问题
根据你描述的情况——getimagesize()在HTTPS下出现和Apache超时时长一致的延迟,HTTP下正常,且图片仅32KB——我来帮你梳理可能的原因和解决方案:
1. 优先方案:直接使用本地文件路径(绕过HTTP/HTTPS请求)
你当前是通过HTTPS URL请求本地服务器上的图片,这完全没必要,反而会引入HTTP请求的开销和潜在的SSL握手问题。直接用本地文件路径调用getimagesize()就能彻底解决延迟问题:
echo "The start time is " . date("h:i:sa"); echo "<br>"; // 构建本地文件路径 $img_path = $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['REQUEST_URI']) . "/assets/img/logo/45.jpg"; print $img_path; echo "<br>"; echo "The time before getimagesize() is " . date("h:i:sa"); echo "<br>"; $img_dimen = getimagesize($img_path); print_r($img_dimen); echo "<br>"; echo "The time after getimagesize() is " . date("h:i:sa"); echo "<br>"; function url(){ return sprintf( "%s://%s%s", isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', $_SERVER['SERVER_NAME'], dirname($_SERVER['REQUEST_URI']) ); }
这个方法跳过了所有HTTP/HTTPS的网络请求逻辑,直接读取本地文件,肯定不会有超时问题,也是性能最优的选择。
2. 如果必须使用HTTPS URL:排查SSL验证问题
PHP 5.6开始默认启用了严格的SSL证书验证,当你的本地HTTPS请求出现证书验证失败时,可能会导致请求重试直到超时。你可以临时关闭SSL验证来测试(仅用于排查,生产环境不建议这么做):
// 在调用getimagesize()前添加这段代码 stream_context_set_default( array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, ) ) ); // 原有的getimagesize()调用 $img_dimen = getimagesize($img_url);
如果这样修改后延迟消失,说明是证书验证的问题。你可以:
- 确保PHP的
openssl.cafile或openssl.capath配置指向正确的CA证书文件(比如Ubuntu上的/etc/ssl/certs/ca-certificates.crt) - 如果是自签名证书,将证书添加到PHP的信任列表中
3. 排查本地回环请求的解析/配置问题
当服务器自身访问自己的HTTPS域名时,可能出现DNS解析或Apache虚拟主机匹配的问题:
- 修改
/etc/hosts文件,将你的域名指向127.0.0.1,避免DNS解析到公网IP再绕回本地的延迟 - 检查Apache的SSL虚拟主机配置,确保
ServerName和ServerAlias与你请求的域名完全匹配,避免Apache在匹配虚拟主机时耗时 - 检查Apache的
ssl.conf配置,是否开启了OCSP Stapling但配置错误(比如OCSP服务器不可达),这会导致SSL握手时的超时
4. 替代方案:手动控制HTTP流的超时设置
如果必须使用URL请求,可以用file_get_contents配合自定义上下文来控制超时,再通过GD库获取图片尺寸,替代getimagesize():
echo "The start time is " . date("h:i:sa"); echo "<br>"; $img_url = url()."/assets/img/logo/45.jpg"; print $img_url; echo "<br>"; echo "The time before fetching image is " . date("h:i:sa"); echo "<br>"; // 创建带有超时和SSL设置的上下文 $context = stream_context_create(array( 'http' => array( 'timeout' => 2, // 设置2秒超时,避免长时间挂起 ), 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, ) )); // 获取图片数据并解析尺寸 $img_data = file_get_contents($img_url, false, $context); if($img_data){ $img = imagecreatefromstring($img_data); $img_dimen = array(imagesx($img), imagesy($img)); imagedestroy($img); print_r($img_dimen); } else { echo "Failed to fetch image"; } echo "<br>"; echo "The time after fetching image is " . date("h:i:sa"); echo "<br>"; function url(){ return sprintf( "%s://%s%s", isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', $_SERVER['SERVER_NAME'], dirname($_SERVER['REQUEST_URI']) ); }
这个方法能更灵活地控制请求的超时和SSL设置,避免getimagesize()底层默认配置导致的超时。
内容的提问来源于stack exchange,提问作者Yamraj
相关产品推荐
相关产品推荐

