GD库出现白屏问题如何解决?
How to solve a white screen problem in the GD library?
我在 GD PHP 库中遇到问题。当我将图像发送到本地主机 VM 时,图像通常会在屏幕上生成,但是当我尝试在 VPS 上执行时,我不会生成图像并且屏幕是白色的。我已经检查过两台机器上的 lib GD 是否相同,一切似乎都没问题。
以下是我在屏幕上生成图像的代码:
$image = imagecreatefrompng((isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]" . "/wp-content/uploads/cart1.png");
$imageCart = imagecreatefrompng($perfil);
$titleColor = imagecolorallocate($image, 255, 255, 255);
$gray = imagecolorallocate($image, 100, 100, 100);
$black = imagecolorallocate($image, 0, 0, 0);
imagecopymerge($image, $imageCart, 60, 177, 0, 0, imagesx($imageCart), imagesy($imageCart), 100);
imagestring($image, 5, 170, 175, "NOME " . strtoupper($nomeCompleto), $titleColor);
imagestring($image, 5, 170, 205, "CPF " . $cpf, $titleColor);
imagestring($image, 5, 170, 235, "MATRICULA " . $matricula, $titleColor);
imagestring($image, 5, 170, 263, "DT NASCIMENTO " . $dtnacimento, $titleColor);
header("Content-type: image/png");
imagepng($image);
imagepng($imageCart);
imagedestroy($image);
imagedestroy($imageCart);
这个问题很有趣,因为评论中报告本地和远程服务器环境相同。通常的问题是 gd
扩展安装在一个中,而在另一个中丢失,但这里不是这种情况。他们甚至被报告为具有相同的内部版本号。
所以第一个问题就在这里:
imagepng($image);
imagepng($imageCart);
imagepng()
函数获取图像的二进制数据并将其发送到 /dev/stdout
,Web 服务器将在此处捕获该数据,并将其传输到请求客户端。拥有其中两个可能会产生奇怪的结果,因为浏览器将看到两个连接的 PNG 图像。如评论中所述,这可能适用于某些浏览器,但可能不适用于其他浏览器 - 换句话说,我们不能依赖它工作。最好只发送有效输出,即使在某些情况下我们可以让它工作(在它工作的地方,浏览器可能使用第一个而丢弃第二个)。所以第一件事就是只发送一张图片。
下一个问题在这一行,调试发现:
$image = imagecreatefrompng((isset($_SERVER['HTTPS']) ? "https" : "http") .
"://$_SERVER[HTTP_HOST]" .
"/wp-content/uploads/cart1.png");
本质上,这会通过 HTTP/HTTPS 加载源 PNG 图像。这利用了 PHP 中允许使用 URL 代替文件路径的功能。来自 the manual:
A URL can be used as a filename with this function if the fopen wrappers have been enabled. See fopen() for more details on how to specify the filename. See the Supported Protocols and Wrappers for links to information about what abilities the various wrappers have, notes on their usage, and information on any predefined variables they may provide.
我会冒险猜测你的 allow_url_fopen
在你的本地机器上是真的,而在你的 VPS 上是假的或没有设置。这本可以通过远程更改来实现,但所做的修复可能更好 - 即直接从文件系统加载它。
如果您使用 fopen 包装器,那么您实际做的是向 Web 服务器发出请求,从磁盘获取图像,然后 returns 通过 curl 获取图像。因此,通过直接使用文件名获取图像,您可以“省去中间人”并更有效地获取图像。
在这些情况下通常使用目录遍历运算符来创建相对于脚本目录的路径名。使用的一个非常好的解决方案是:
imagecreatefrompng("../../../wp-content/uploads/cart1.png")
你也可以使用魔法变量(假设脚本在项目根目录下三级):
$projectDir = realpath(__DIR__ . "/../../..");
imagecreatefrompng($projectDir . "/wp-content/uploads/cart1.png")
您可能会发现 WordPress 设置了一些它自己的项目目录常量,因此在这种情况下也可以使用它们。
我在 GD PHP 库中遇到问题。当我将图像发送到本地主机 VM 时,图像通常会在屏幕上生成,但是当我尝试在 VPS 上执行时,我不会生成图像并且屏幕是白色的。我已经检查过两台机器上的 lib GD 是否相同,一切似乎都没问题。
以下是我在屏幕上生成图像的代码:
$image = imagecreatefrompng((isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]" . "/wp-content/uploads/cart1.png");
$imageCart = imagecreatefrompng($perfil);
$titleColor = imagecolorallocate($image, 255, 255, 255);
$gray = imagecolorallocate($image, 100, 100, 100);
$black = imagecolorallocate($image, 0, 0, 0);
imagecopymerge($image, $imageCart, 60, 177, 0, 0, imagesx($imageCart), imagesy($imageCart), 100);
imagestring($image, 5, 170, 175, "NOME " . strtoupper($nomeCompleto), $titleColor);
imagestring($image, 5, 170, 205, "CPF " . $cpf, $titleColor);
imagestring($image, 5, 170, 235, "MATRICULA " . $matricula, $titleColor);
imagestring($image, 5, 170, 263, "DT NASCIMENTO " . $dtnacimento, $titleColor);
header("Content-type: image/png");
imagepng($image);
imagepng($imageCart);
imagedestroy($image);
imagedestroy($imageCart);
这个问题很有趣,因为评论中报告本地和远程服务器环境相同。通常的问题是 gd
扩展安装在一个中,而在另一个中丢失,但这里不是这种情况。他们甚至被报告为具有相同的内部版本号。
所以第一个问题就在这里:
imagepng($image);
imagepng($imageCart);
imagepng()
函数获取图像的二进制数据并将其发送到 /dev/stdout
,Web 服务器将在此处捕获该数据,并将其传输到请求客户端。拥有其中两个可能会产生奇怪的结果,因为浏览器将看到两个连接的 PNG 图像。如评论中所述,这可能适用于某些浏览器,但可能不适用于其他浏览器 - 换句话说,我们不能依赖它工作。最好只发送有效输出,即使在某些情况下我们可以让它工作(在它工作的地方,浏览器可能使用第一个而丢弃第二个)。所以第一件事就是只发送一张图片。
下一个问题在这一行,调试发现:
$image = imagecreatefrompng((isset($_SERVER['HTTPS']) ? "https" : "http") .
"://$_SERVER[HTTP_HOST]" .
"/wp-content/uploads/cart1.png");
本质上,这会通过 HTTP/HTTPS 加载源 PNG 图像。这利用了 PHP 中允许使用 URL 代替文件路径的功能。来自 the manual:
A URL can be used as a filename with this function if the fopen wrappers have been enabled. See fopen() for more details on how to specify the filename. See the Supported Protocols and Wrappers for links to information about what abilities the various wrappers have, notes on their usage, and information on any predefined variables they may provide.
我会冒险猜测你的 allow_url_fopen
在你的本地机器上是真的,而在你的 VPS 上是假的或没有设置。这本可以通过远程更改来实现,但所做的修复可能更好 - 即直接从文件系统加载它。
如果您使用 fopen 包装器,那么您实际做的是向 Web 服务器发出请求,从磁盘获取图像,然后 returns 通过 curl 获取图像。因此,通过直接使用文件名获取图像,您可以“省去中间人”并更有效地获取图像。
在这些情况下通常使用目录遍历运算符来创建相对于脚本目录的路径名。使用的一个非常好的解决方案是:
imagecreatefrompng("../../../wp-content/uploads/cart1.png")
你也可以使用魔法变量(假设脚本在项目根目录下三级):
$projectDir = realpath(__DIR__ . "/../../..");
imagecreatefrompng($projectDir . "/wp-content/uploads/cart1.png")
您可能会发现 WordPress 设置了一些它自己的项目目录常量,因此在这种情况下也可以使用它们。