Create Apache dynamic image / headers using Imagick

When porting an existing, stable website to a new server, I ran into an intermittent problem with a small amount of code that dynamically creates images using Imagick.

The code parses a GET request (for example, example.com/image.php?ipid=750123&r=0&w=750&h=1000), and then scales and rotates the image stored on the server and serves its client.

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

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

When moving to a new, much faster server (from Debian Squeeze to Ubuntu 12.04), I encounter a problem where in about 50% of cases the image is not displayed, and instead the server sends a 0 byte "png file". PHP errors or server errors do not exist.

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

Successful image headers:

 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 

Image Header Failure:

 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 idea why this is happening?

Is there a way to get "png images" to send chunked, since I am wondering if this is at the root of the problem. I tried various workarounds when I send the image size, or "Transfer-encoding: chunked" as a header via the PHP header () function, but it doesnโ€™t work, and in these cases the browser claims that 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); ?> 

UPDATE: in case this helps locate the problem:

I created a universal workaround that works in all cases, as a stop measure. I create an 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. It is cumbersome, and I would prefer to do it in a โ€œneatโ€ way, but it seems to me that the problem is with these two lines: header('Content-type:image/png'); echo $img->getImage(); header('Content-type:image/png'); echo $img->getImage(); and Apache, PHP, or Imagick crashes to process the resource.

+6
source share
2 answers

I had a problem very similar to the previous one and it was related to the second request with a heading forward with a status code of 301 or 302. Some browsers do not follow

Both images return 200 or are failed return redirections?

+3
source

Maybe a long shot, but maybe there is some unintended output before calling echo $img->getImage() ? This will damage the output image. I came across this earlier with the ending new line character after closing the ?> Tag in some random include() .

A quick test before clearing your code will be to use output buffering to destroy everything before displaying image data.

 <?php ob_start(); //call this before executing ANY other php ?> 

Some time later...

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

Of course, you will mention a stable code base, but different versions of the web server or php may relate to this unintentional gap differently.

EDIT: Another thought

Is it possible that some php output caching mechanism is running on the new server. Perhaps he is trying to reload the newly created image from the cache somewhere, and this part does not work, which may be the best explanation for the content length of 0 bytes. Perhaps the new server simply phpinfo(); not have a library ... compare the output of phpinfo(); on each server.

+2
source

Source: https://habr.com/ru/post/950111/


All Articles