Durante il trasferimento di un sito Web esistente, stabile a un nuovo server, si è verificato un problema intermittente con un po 'di codice che crea immagini dinamicamente utilizzando Imagick.Creazione di immagini dinamiche/intestazioni Apache utilizzando Imagick
Il codice analizza una query GET (es example.com/image.php?ipid=75 r = 0 & w = 750 & h = 1000) e quindi scala e ruota un'immagine memorizzata sul server e lo serve al cliente.
ipid = id for an image stored on server
r = degrees of rotation
w = width to display
h = height to display.
Il codice è stato probabilmente utilizzato per almeno 5 anni senza problemi.
Durante il trasferimento a un server nuovo, molto più veloce (da Debian Squeeze a Ubuntu 12.04), si verifica un problema in cui circa il 50% delle volte l'immagine non viene visualizzata e il server invia un "file png" di 0 byte. Non ci sono errori PHP o errori del server.
A seconda che le immagini vengono inviate con successo o no, diverse intestazioni vengono inviati:
successo intestazioni immagine:
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
falliti immagine intestazioni:
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
Qualcuno ha qualche idea del perché questo sta accadendo?
C'è un modo per "forzare" le immagini PNG da inviare in blocco, poiché mi chiedo se sia alla radice del problema. Ho provato varie soluzioni alternative in cui invio la dimensione dell'immagine, o "Transfer-Encoding: chunked" come intestazione tramite la funzione header() di PHP, ma non ha funzionato, e in questi casi il browser afferma che l'immagine è corrotta.
<?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: Nel caso in cui aiuta a identificare la posizione del problema:
Ho creato una soluzione cludgy che funziona in tutti i casi, come un palliativo. Quello che faccio è creare l'immagine, salvarla su disco come un file temporaneo. Aprire il file e inviarlo al client usando passthru() e quindi eliminare il file dal disco. Ingombrante, e preferirei farlo in modo 'ordinato', ma mi suggerisce che il problema è in qualche modo associato a queste due linee: header('Content-type:image/png'); echo $img->getImage();
e un errore da parte di Apache, PHP o Imagick per gestire la risorsa.
lunghezza del contenuto di '0'? La codifica Chunked non dovrebbe essere necessaria. Mostra il codice effettivo che stai utilizzando per generare l'immagine. Le intestazioni da soli sono inutili. –
Il codice corrente: http://phpfiddle.org/main/code/mkd-tjr – fred2
Per chiarire, la stessa immagine apparirà una volta con contenuto-Lunghezza di 0, e la prossima volta con Transfer Encoding: chunked. Sembra essere un comportamento casuale. – fred2