Php 使用Imagick创建动态图像/Apache头
在将一个现有的、稳定的网站传输到一个新服务器时,我遇到了一个间歇性的问题,其中有一些代码使用Imagick动态创建图像 代码解析GET查询(例如example.com/image.php?ipid=750123&r=0&w=750&h=1000),然后缩放和旋转存储在服务器上的图像,并将其提供给客户端Php 使用Imagick创建动态图像/Apache头,php,apache2,imagemagick,imagick,Php,Apache2,Imagemagick,Imagick,在将一个现有的、稳定的网站传输到一个新服务器时,我遇到了一个间歇性的问题,其中有一些代码使用Imagick动态创建图像 代码解析GET查询(例如example.com/image.php?ipid=750123&r=0&w=750&h=1000),然后缩放和旋转存储在服务器上的图像,并将其提供给客户端 ipid = id for an image stored on server r = degrees of rotation w = width to display h = height to
ipid = id for an image stored on server
r = degrees of rotation
w = width to display
h = height to display.
该代码可能已经使用了至少5年,没有任何问题
在转移到一个新的、快得多的服务器(从Debian Squence到Ubuntu 12.04)时,我遇到了一个问题,大约50%的时间图像没有显示,而服务器发送了一个0字节的“png文件”。没有PHP错误或服务器错误
根据图像是否成功发送,将发送不同的标头:
成功的图像标题:
Connection: Keep-Alive
Content-Type: image/png
Date: Tue, 23 Jul 2013 17:03:32 GMT
Keep-Alive: timeout=5, max=76
Server: Apache/2.2.22 (Ubuntu)
Transfer-Encoding: chunked
X-Powered-By: PHP/5.3.10-1ubuntu3.7
失败的图像标题:
Connection Keep-Alive
Content-Length 0
Content-Type image/png
Date Tue, 23 Jul 2013 17:03:31 GMT
Keep-Alive timeout=5, max=78
Server Apache/2.2.22 (Ubuntu)
X-Powered-By PHP/5.3.10-1ubuntu3.7
有人知道为什么会这样吗
有没有办法“强制”将png图像分块发送,因为我想知道这是否是问题的根源。我尝试过各种解决方法,通过PHP的header()函数将图像大小或“Transfer Encoding:chunked”作为标题发送,但没有成功,在这些情况下,浏览器会声明图像已损坏
<?php
//Class used to connect to Imagick and do image manipulation:
class Images
{
public $image = null;
public function loadImage($imagePath){
$this->image = new Imagick();
return $this->image->readImage($imagePath);
}
public function getImage(){
$this->image->setImageFormat("png8");
$this->image->setImageDepth(5);
$this->image->setCompressionQuality(90);
return $this->image;
}
// Resize an image by given percentage.
// percentage must be set as float between 0.01 and 1
public function resizeImage ($percentage = 1, $maxWidth = false, $maxHeight = false)
{
if(!$this->image){return false;}
if($percentage==1 && $maxWidth==false && $maxHeight == false){return true;}
$width = $this->image->getImageWidth();
$height = $this->image->getImageHeight();
$newWidth = $width;
$newHeight = $height;
if($maxHeight && $maxWidth){
if($height > $maxHeight || $width > $maxWidth){
$scale = ($height/$maxHeight > $width/$maxWidth) ? ($height/$maxHeight) : ($width/$maxWidth) ;
$newWidth = (int) ($width / $scale);
$newHeight = (int) ($height / $scale);
}
}else{
$newWidth = $width * $percentage;
$newHeight = $height * $percentage;
}
return $this->image->resizeImage($newWidth,$newHeight,Imagick::FILTER_LANCZOS,1);
}
public function resizeImageByWidth ($newWidth)
{
if ($newWidth > 3000){
$newWidth = 3000; //Safety measure - don't allow crazy sizes to break server.
}
if(!$this->image){return false;}
return $this->image->resizeImage($newWidth,0,Imagick::FILTER_LANCZOS,1);
}
public function rotateImage($degrees=0)
{
if(!$this->image){return false;}
return $this->image->rotateImage(new ImagickPixel(), $degrees);
}
}
//(simplified version of) procedural code that outputs the image to browser:
$img = new Images();
$imagePath = '/some/path/returned/by/DB/image.png';
if($imagePath){
$img->loadImage($imagePath);
$width = $img->image->getImageWidth();
$height = $img->image->getImageHeight();
if (!$img->resizeImageByWidth($newWidth))
{
die ("image_error: resizeImage() could not create image.");
}
if($rotation > 0){
if (!$img->rotateImage($rotation))
{
die ("image_error: rotateImage() could not create image.");
}
}
}else{
die("image_error: no image path specified");
}
header('Content-type:image/png');
echo $img->getImage();
exit(0);
?>
我以前遇到过一个与此非常类似的问题,它与第二个请求有关,该请求的头转发了301或302状态代码。有些浏览器不遵循这一点
这两个图像都返回200,还是失败的图像返回重定向?可能不太可能,但在echo$img->getImage()调用之前可能有一些意外的输出?这将损坏输出图像。我以前在一些随机的include()
中,在关闭?>
标记之后遇到了一个尾随的新行字符
在清理代码之前的一个快速测试是,在输出图像数据之前,使用输出缓冲区清除任何内容
<?php
ob_start(); //call this before executing ANY other php
?>
过了一段时间
<?php
ob_clean(); //trash invalid data in the output buffer
//set proper headers for image output and browser caching if desired
echo $img->getImage();
ob_end_flush(); //send the buffered image data to the browser
?>
诚然,您确实提到了一个稳定的代码库,但不同的web服务器或php版本可能会以不同的方式处理意外的空白
编辑:另一个想法
新服务器是否可能正在运行某种php输出缓存机制。也许它正试图从某个缓存中重新加载最近生成的图像,但该部分失败了,这可能是对0字节内容长度的更好解释。也许新服务器只是缺少一个库。。。比较phpinfo()的输出代码>在每台服务器上。内容长度0
?分块编码应该是不必要的。显示用于生成图像的实际代码。标题本身是无用的。当前代码:为了澄清,同一图像将出现一次,内容长度为0,下一次使用传输编码:chunked。这似乎是随机行为。两台服务器上是否安装了不同版本的ImageMagick?测试$img->loadImage($imagePath)的返回代码>可能你一开始没有得到图像,所以没有任何输出。嗨,谢谢你的回复。不,对不起。两张图片都返回200。你能给我发一个图片链接吗?这可能有点困难,因为它是在一个密码保护的网站上,但是如果我在接下来的一个小时左右没有得到任何其他建议,我会看看我能做些什么。本质上,我相信你只能在原始帖子中看到信息,这不是一个完整的标题。当你的错误日志不起作用时,你也检查过它了吗?是的,不幸的是没有抛出错误。将检查更完整的标题。不,对不起,没有空白。缓存是一个好主意-在记住新服务器上还没有任何缓存之前,我想可能就是这样!是否依赖于代码库中的缓存?也许这就是问题的根源。