使用 Imagick 创建动态图像/Apache 标头 [英] Dynamic image creation/Apache headers using Imagick

查看:28
本文介绍了使用 Imagick 创建动态图像/Apache 标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将现有的、稳定的网站转移到新服务器时,我遇到了一些使用 Imagick 动态创建图像的代码的间歇性问题.

While transferring an existing, stable, website to a new server I've run into an intermittent problem with a bit of code that creates images dynamically using Imagick.

该代码解析 GET 查询(例如 example.com/image.php?ipid=750123&r=0&w=750&h=1000),然后缩放和旋转存储在服务器上的图像并将其提供给客户.

The code parses a GET query (eg example.com/image.php?ipid=750123&r=0&w=750&h=1000) and then scales and rotates an image stored on the server and serves it to the client.

ipid = id for an image stored on server
r = degrees of rotation
w = width to display
h = height to display.

该代码可能已经使用了至少 5 年没有问题.

The code has probably been used for at least 5 years with no problems.

在转移到新的、速度更快的服务器(从 Debian Squeeze 到 Ubuntu 12.04)时,我遇到了一个问题,大约 50% 的时间图像不显示,而是服务器发送一个png 文件"0 字节.没有 PHP 错误或服务器错误.

On transferring to a new, much faster, server (from Debian Squeeze to Ubuntu 12.04), I encounter a problem where about 50% of the time the image does not display, and instead the server sends a 'png file' of 0 bytes. There are no PHP errors or server errors.

根据图片是否发送成功,发送不同的header:

Depending on whether the images is sent successfully or not, different headers are sent:

成功的图片标题:

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

有人知道为什么会发生这种情况吗?

Does anyone have any ideas why this is happening?

有没有办法强制"将 png 图像分块发送,因为我想知道这是否是问题的根源.我尝试了各种解决方法,通过 PHP 的 header() 函数发送图像大小或传输编码:分块"作为标头,但没有奏效,在这些情况下,浏览器指出图像已损坏.

Is there a way to 'force' the png images to be sent chunked, as I wonder if that is at the root of the problem. I've tried various workarounds where I send the image size, or 'Transfer-Encoding: chunked' as a header via PHP's header() function, but did not work, and in these cases the browser states the image is corrupted.

<?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);
?>

更新:如果它有助于确定问题的位置:

作为权宜之计,我创建了一个适用于所有情况的笨拙解决方法.我所做的是创建图像,将其作为临时文件保存到磁盘.打开文件并使用 passthru() 将其发送到客户端,然后从磁盘中删除该文件.麻烦,我宁愿用整洁"的方式来做,但它向我表明问题与这两行有某种关联: header('Content-type:image/png');echo $img->getImage(); 以及 Apache、PHP 或 Imagick 处理资源失败.

I've created a cludgy workaround which works in all cases, as a stopgap measure. What I do is create the image, save it to disk as a temporary file. Open the file and send it to the client using passthru() and then delete the file from disk. Cumbersome, and I'd rather do it the 'tidy' way, but it suggests to me the problem is somehow associated with these two lines: header('Content-type:image/png'); echo $img->getImage(); and a failure by Apache, PHP or Imagick to handle the resource.

推荐答案

我之前遇到过一个与此非常相似的问题,它与第二个请求的标题转发以及 301 或 302 状态代码有关.有些浏览器不遵循

I've had an issue very similar to this before and it was related to the second request having a header forward with a 301 or 302 status code. Some browsers don't follow

两个图像都返回 200 还是失败的图像返回重定向?

Are both images returning 200 or is the failed one returning a redirect ?

这篇关于使用 Imagick 创建动态图像/Apache 标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆