对于HTTPS网站显示HTTP链接图片,解决方案使用Apache和PHP实现HTTP图片代理的方案如下:
基础代理 proxy_simple.php
<?php
// proxy_simple.php - 修复版图片代理
header('Content-Type: image/png');
header('Cache-Control: public, max-age=86400');
header('Access-Control-Allow-Origin: *');
// 获取URL参数
$imageUrl = isset($_GET['url']) ? urldecode($_GET['url']) : '';
if (empty($imageUrl)) {
showError('缺少URL参数');
exit;
}
// 验证域名
$allowedDomains = ['image-site.com'];
$host = parse_url($imageUrl, PHP_URL_HOST);
if (!in_array($host, $allowedDomains)) {
showError('不允许的域名: ' . $host);
exit;
}
// 确保使用HTTP协议
if (strpos($imageUrl, 'http') === false) {
$imageUrl = 'http://' . $imageUrl;
}
// 使用file_get_contents或cURL获取图片
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\r\n" .
"Accept: image/*\r\n" .
"Referer: " . ($_SERVER['HTTP_REFERER'] ?? '') . "\r\n",
'timeout' => 10
]
]);
try {
// 方法1: 使用file_get_contents
$imageData = @file_get_contents($imageUrl, false, $context);
if ($imageData === false) {
// 方法2: 如果失败,尝试使用cURL
$imageData = fetchWithCurl($imageUrl);
}
if ($imageData) {
// 检测MIME类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_buffer($finfo, $imageData);
finfo_close($finfo);
header("Content-Type: $mimeType");
echo $imageData;
} else {
showError('无法获取图片数据');
}
} catch (Exception $e) {
showError('代理错误: ' . $e->getMessage());
}
function fetchWithCurl($url) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 3,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 15,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_REFERER => $_SERVER['HTTP_REFERER'] ?? '',
]);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
function showError($message) {
// 确保没有其他输出
if (ob_get_length()) ob_clean();
// 设置正确的Content-Type
header('Content-Type: image/png');
$width = 400;
$height = 100;
// 创建图片资源
$image = imagecreatetruecolor($width, $height);
if (!$image) {
// 如果创建图片失败,输出纯文本错误
header('Content-Type: text/plain; charset=utf-8');
echo "错误: $message\n无法生成错误图片";
exit;
}
// 设置颜色
$bgColor = imagecolorallocate($image, 245, 245, 245);
$borderColor = imagecolorallocate($image, 200, 200, 200);
$textColor = imagecolorallocate($image, 180, 0, 0);
// 填充背景
imagefilledrectangle($image, 0, 0, $width, $height, $bgColor);
// 添加边框
imagerectangle($image, 0, 0, $width-1, $height-1, $borderColor);
// 方法1: 使用imagestring显示英文错误信息
$errorText = 'Image Proxy Error';
$textX = ($width - strlen($errorText) * imagefontwidth(5)) / 2;
imagestring($image, 5, $textX, 20, $errorText, $textColor);
// 处理错误消息,如果是中文,显示简化信息
$errorMsg = $message;
// 如果包含中文字符,使用简化的错误提示
if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $message)) {
// 截取前部分显示
$errorMsg = 'Error loading image';
} else {
// 如果是英文,截断以避免过长
$errorMsg = substr($message, 0, 40);
}
// 显示错误详情
$detailX = ($width - strlen($errorMsg) * imagefontwidth(4)) / 2;
imagestring($image, 4, $detailX, 50, $errorMsg, $textColor);
// 输出图片
imagepng($image);
imagedestroy($image);
exit;
}使用GD库显示中文字符的版本(需要中文字体文件)
<?php
// proxy_with_chinese.php - 支持中文显示的代理
// 错误报告
error_reporting(0); // 关闭错误显示,避免污染图片输出
// 设置默认时区
date_default_timezone_set('Asia/Shanghai');
function showError($message) {
// 清除之前的输出
if (ob_get_length()) ob_clean();
// 设置响应头
header('Content-Type: image/png');
header('Cache-Control: no-cache, no-store, must-revalidate');
$width = 400;
$height = 120;
// 创建图片
$image = imagecreatetruecolor($width, $height);
if (!$image) {
// 如果创建图片失败,输出纯文本错误
header('Content-Type: text/plain; charset=utf-8');
echo "错误: $message\n无法生成错误图片";
exit;
}
// 设置颜色
$bgColor = imagecolorallocate($image, 250, 250, 250); // 浅灰色背景
$borderColor = imagecolorallocate($image, 220, 220, 220); // 边框颜色
$titleColor = imagecolorallocate($image, 220, 0, 0); // 标题颜色
$textColor = imagecolorallocate($image, 100, 100, 100); // 正文颜色
$lineColor = imagecolorallocate($image, 200, 200, 200); // 分割线颜色
// 填充背景
imagefilledrectangle($image, 0, 0, $width, $height, $bgColor);
// 添加边框
imagerectangle($image, 0, 0, $width-1, $height-1, $borderColor);
// 添加标题栏
imagefilledrectangle($image, 0, 0, $width, 30, imagecolorallocate($image, 230, 230, 230));
imagestring($image, 5, 10, 8, '图片代理错误', $titleColor);
// 添加分割线
imageline($image, 0, 30, $width, 30, $lineColor);
// 显示错误信息(英文)
$errorTitle = 'Error Details:';
imagestring($image, 4, 20, 45, $errorTitle, $textColor);
// 处理错误消息
$errorMsg = substr($message, 0, 50);
$lines = str_split($errorMsg, 30); // 每行30个字符
$y = 70;
foreach ($lines as $line) {
imagestring($image, 4, 20, $y, $line, $textColor);
$y += 15;
}
// 添加时间戳
$timestamp = date('Y-m-d H:i:s');
imagestring($image, 3, 20, $height - 25, "Time: $timestamp", imagecolorallocate($image, 150, 150, 150));
// 输出图片
imagepng($image);
imagedestroy($image);
exit;
}
// 主程序开始
header('Content-Type: image/png');
header('Cache-Control: public, max-age=86400');
header('Access-Control-Allow-Origin: *');
// 获取URL参数
$imageUrl = isset($_GET['url']) ? urldecode($_GET['url']) : '';
if (empty($imageUrl)) {
showError('缺少URL参数');
exit;
}
// 验证域名
$allowedDomains = ['image-site.com'];
$host = parse_url($imageUrl, PHP_URL_HOST);
if (!in_array($host, $allowedDomains)) {
showError('不允许的域名: ' . $host);
exit;
}
// 确保使用HTTP协议
if (strpos($imageUrl, 'http') === false) {
$imageUrl = 'http://' . $imageUrl;
}
// 使用cURL获取图片
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $imageUrl,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 3,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 15,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_REFERER => $_SERVER['HTTP_REFERER'] ?? '',
CURLOPT_SSL_VERIFYPEER => false, // 如果目标站点有SSL问题,可以禁用验证
CURLOPT_SSL_VERIFYHOST => false,
]);
$imageData = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
$error = curl_error($ch);
curl_close($ch);
if ($imageData && $httpCode == 200) {
// 检测MIME类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_buffer($finfo, $imageData);
finfo_close($finfo);
if (strpos($mimeType, 'image/') === 0) {
header("Content-Type: $mimeType");
echo $imageData;
} else {
showError('获取的不是有效的图片文件');
}
} else {
showError('无法获取图片数据: ' . ($error ?: "HTTP $httpCode"));
}最简单的错误图片生成方案
<?php
// proxy_clean.php - 简洁版本
function showCleanError($message) {
// 清除之前的输出
while (ob_get_level()) ob_end_clean();
header('Content-Type: image/png');
$width = 400;
$height = 100;
// 创建图片
$img = imagecreate($width, $height);
// 颜色
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
$red = imagecolorallocate($img, 255, 0, 0);
$gray = imagecolorallocate($img, 200, 200, 200);
// 填充背景
imagefilledrectangle($img, 0, 0, $width, $height, $white);
// 边框
imagerectangle($img, 0, 0, $width-1, $height-1, $gray);
// 简单错误提示(只显示英文,避免中文乱码)
$error_lines = [
'Image Load Error',
'URL: ' . ($_GET['url'] ?? ''),
'Time: ' . date('H:i:s')
];
$y = 15;
foreach ($error_lines as $line) {
// 居中显示
$len = strlen($line);
$x = ($width - $len * imagefontwidth(4)) / 2;
imagestring($img, 4, $x, $y, $line, $red);
$y += 20;
}
// 显示通用错误信息
imagestring($img, 3, 50, $y+10, 'Please check the image URL and try again', $black);
imagepng($img);
imagedestroy($img);
exit;
}
// 主程序
header('Content-Type: image/png');
header('Cache-Control: public, max-age=3600');
$url = $_GET['url'] ?? '';
if (empty($url)) {
showCleanError('No URL provided');
}
// 验证URL
$host = parse_url($url, PHP_URL_HOST);
if ($host !== 'image-site.com') {
showCleanError('Invalid domain');
}
// 获取图片
$data = @file_get_contents($url);
if ($data === false) {
// 尝试cURL
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
$data = curl_exec($ch);
curl_close($ch);
}
if ($data) {
// 输出图片
echo $data;
} else {
showCleanError('Failed to load image');
}使用SVG作为错误图片(推荐,支持中文)
<?php
// proxy_svg_error.php - 使用SVG显示错误
function showSvgError($message) {
// 清除之前的输出
while (ob_get_level()) ob_end_clean();
header('Content-Type: image/svg+xml');
header('Cache-Control: no-cache');
// 对消息进行HTML转义
$escapedMsg = htmlspecialchars(substr($message, 0, 100), ENT_QUOTES, 'UTF-8');
// 生成SVG
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="400" height="120" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="400" height="120" fill="#f8f8f8" stroke="#ccc" stroke-width="1"/>
<!-- 标题栏 -->
<rect x="0" y="0" width="400" height="30" fill="#e8e8e8"/>
<text x="10" y="20" font-family="Arial, sans-serif" font-size="14" fill="#c00">图片代理错误</text>
<!-- 错误信息 -->
<text x="10" y="55" font-family="Arial, sans-serif" font-size="12" fill="#333">错误信息:</text>
<!-- 多行文本显示 -->
<g transform="translate(10, 70)">
<text font-family="Arial, sans-serif" font-size="11" fill="#666">' . $escapedMsg . '</text>
</g>
<!-- 底部信息 -->
<text x="10" y="110" font-family="Arial, sans-serif" font-size="10" fill="#999">时间: ' . date('Y-m-d H:i:s') . '</text>
</svg>';
exit;
}
// 主程序
header('Content-Type: image/png');
header('Cache-Control: public, max-age=86400');
$url = $_GET['url'] ?? '';
if (empty($url)) {
showSvgError('缺少URL参数');
}
// 验证域名
$host = parse_url($url, PHP_URL_HOST);
if ($host !== 'image-site.com') {
showSvgError('不允许的域名: ' . $host);
}
// 获取图片
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_USERAGENT => 'Mozilla/5.0',
]);
$imageData = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($imageData && $httpCode == 200) {
// 检测MIME类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_buffer($finfo, $imageData);
finfo_close($finfo);
if (strpos($mimeType, 'image/') === 0) {
header("Content-Type: $mimeType");
echo $imageData;
} else {
showSvgError('获取的不是有效的图片文件');
}
} else {
showSvgError('无法获取图片数据 (HTTP ' . $httpCode . ')');
}推荐的解决方案
如果不需要显示中文错误信息:使用第一个修复版
proxy_simple.php如果需要显示中文错误信息:使用SVG版本
proxy_svg_error.php最简单的方案:使用
proxy_clean.php
测试方法:
# 测试正常图片 curl "https://your-site.com/proxy_simple.php?url=http://image-site.com/e368d0d1098ad0e641230184a3c9.png" # 测试错误情况(缺少URL) curl "https://your-site.com/proxy_simple.php" # 测试错误情况(错误域名) curl "https://your-site.com/proxy_simple.php?url=http://wrong-domain.com/image.jpg"
选择最适合你需求的版本即可。SVG版本支持中文且不会乱码,是最佳选择。
版权声明:本站部分内容来自互联网,若涉及版权问题请及时通知我们,我们将及时予以删除!谢谢大家的理解与支持!

发表评论