开发者

PHP: problem rendering large images (error 321)

开发者 https://www.devze.com 2023-02-01 08:56 出处:网络
its me again with a php problem :) Following is part of my PHP 开发者_运维知识库script which is rendering JPEG images.

its me again with a php problem :)

Following is part of my PHP 开发者_运维知识库script which is rendering JPEG images.

...
$tf=$requested_file;
$image_type="jpeg";
header("Content-type: image/${image_type}");
$CMD="\$image=imagecreatefrom${image_type}('$tf'); image${image_type}(\$image);";
eval($CMD);
exit;
...

There is no syntactical error, because above code is working fine for small images, but for large images, it gives:

Error 321 (net::ERR_INVALID_CHUNKED_ENCODING): Unknown error. in the browser.

To be sure, I created two images using imagemagick from same source image - one resized to 10% of original and other 90%.

http://mostpopularsports.net/images/misc/ttt10.jpg works

http://mostpopularsports.net/images/misc/ttt90.jpg gives Error 301 in the browser.

There is a related question with solution posted by OP here Error writing content through Apache but I cannot understand how to make the fix. Can someome help me with it?

I have looked at the headers in Chrome. For the first request, everything is fine. For the second request - the request headers are all garbled.


Both images are jpeg (as they are created from imagemagick. But still to be sure I checked):

misc/ttt10.jpg: JPEG image data, JFIF standard 1.01
misc/ttt90.jpg: JPEG image data, JFIF standard 1.01

Finally, the way I fixed is, remove the Transfer-Encoding: chunked header from the response. [This header was sent by apache only when the data was large enough]. (I had an internal proxy, so did it in the proxy script - otherwise one may need to do it in apache settings).

There were some good answers and I have selected the one that helped me solve the problem best.

thanks

JP


I'm not going to answer directly to your question, but I have to say something about your use of eval, which is highly unnecessary in this case (as in every other case as well).

You can do this instead and avoid shooting yourself in the leg:

header("Content-type: image/${image_type}");
$image = imagecreatefromstring(file_get_contents($tf));
switch($image_type) {
    case 'jpeg':
    case 'jpg':
        imagejpeg($image);
        break;
    case 'png':
        imagepng($image);
        break;
    case 'gif':
        imagegif($image);
        break;
}


Currently you always send the content-type header as JPEG, even-though the image might be something else (PNG/GIF?). This could cause some trouble too.

Also, you really shouldnt use eval like that. What are you trying to achieve?


You should debug the exact server response using netcat. But a quick look with wget --save-headers reveals that the output actually looks ok:

HTTP/1.1 200 OK
Date: Wed, 29 Dec 2010 12:16:03 GMT
Server: Apache/2.2.14 (Ubuntu)
X-Powered-By: PHP/5.2.6-3ubuntu4.6
Set-Cookie: PHPSESSID=sjh4k63i9npk6b15uperclau75; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive, Keep-Alive
Transfer-Encoding: chunked
Content-Type: image/jpeg

Your linked bug-report had an invalid "chunked,chunked" - which isn't the case for your script. Still the chunked encoding is the problem here, as your Chrome error message shows.

I think the problem might be PHPs output buffers. The transfer-encoding lacks the final 0\r\n to terminate the HTTP stream.

You can try flush(), disabling PHPs output buffer, and also Apaches mod_deflate (which is an extra buffer). I'm clueless as to why PHP keeps the connection open, but it might very well be the specifc combination of eval and exit. Try rewriting your code:

header("Content-type: image/${image_type}");
flush();
$func = "imagecreatefrom${image_type}";
$image = $func($tf);
$func = "image${image_type}";
$func($image);
flush();
exit;

Or if it doesn't work. Try outputting garbage echo "0"; after the image.

0

精彩评论

暂无评论...
验证码 换一张
取 消