通过“print fread(...)”提供图像很慢,该怎么办?
我在网上找到了一个动态缩略图脚本,并对其进行了一些调整。我添加的内容之一是缓存机制。每当生成新缩略图时,都会将其保存到磁盘,并且如果再次请求相同的缩略图(具有所有相同的选项),将使用磁盘副本。
片段:
// name of cached file
$thumb_file = $_SERVER['DOCUMENT_ROOT'].'/thumbs/cache/'.
str_replace('/', '_', $_REQUEST['p']).
".{$def_width}x{$def_height}".
($clamp ? '_'.implode('x',$clamp) : '').
($make_png?'.png':'.jpg');
// get it from cache if it's there
if ($use_cache && file_exists($thumb_file)) {
Header("Content-type: image/".($make_png?'png':'jpeg'));
// this part seems really slow
$fp=fopen($thumb_file, "rb");
while (!feof($fp)) print fread($fp, 4096);
exit();
}
但是,打印
fread的结果似乎非常慢,有时(非常罕见)图像无法完全加载。
那么,我怎样才能加快速度呢?我应该将浏览器重定向到图像而不是读取它,还是还有其他选择?
我在下面提供了完整的 PHP 脚本,以防万一。
<?php
$use_cache = $_REQUEST['nc'] ? false : true;
// $use_cache = false;
$upfile = $_SERVER['DOCUMENT_ROOT'] .'/'. $_REQUEST['p'];
$def_width = $_REQUEST["w"];
$def_height = $_REQUEST["h"];
$clamp = $_REQUEST['c'] ? explode("x",$_REQUEST['c']) : null;
$make_png = $_REQUEST['png'];
if (!file_exists($upfile)) {
die(); // $upfile = "nophoto.jpg";
}
if (!"{$def_width}{$def_height}") {
$def_width = $def_height = '100';
}
// name of cached file
$thumb_file = $_SERVER['DOCUMENT_ROOT'].'/thumbs/cache/'.
str_replace('/', '_', $_REQUEST['p']).
".{$def_width}x{$def_height}".
($clamp ? '_'.implode('x',$clamp) : '').
($make_png?'.png':'.jpg');
// get it from cache if it's there
if ($use_cache && file_exists($thumb_file)) {
Header("Content-type: image/".($make_png?'png':'jpeg'));
$fp=fopen($thumb_file, "rb");
while (!feof($fp)) print fread($fp, 4096);
exit();
}
$ext = strtolower(substr($upfile, -3));
ini_set('memory_limit', '64M');
if ($ext=="gif")
$src = @ImageCreateFromGif ($upfile);
else if ($ext=="jpg")
$src = @ImageCreateFromJpeg($upfile);
else if ($ext=="png")
$src = @ImageCreateFromPng($upfile);
$size = GetImageSize($upfile);
$width = $size[0];
$height = $size[1];
$long_side = $def_width;
if ($def_width < $def_height) $long_side = $def_height;
if (!$def_width) {
$factor_h = $height / $def_height;
$def_width = $width / $factor_h;
}
if (!$def_height) {
$factor_w = $width / $def_width;
$def_height = $height / $factor_w;
}
$factor_w = $width / $def_width;
$factor_h = $height / $def_height;
if ($factor_w > $factor_h) {
$new_height = floor($def_height * $factor_h);
$new_width = floor($def_width * $factor_h);
} else {
$new_height = floor($def_height * $factor_w);
$new_width = floor($def_width * $factor_w);
}
if ((!$clamp[0])&&$clamp[0]!=='0') $clamp[0] = 50;
if ((!$clamp[1])&&$clamp[1]!=='0') $clamp[1] = 50;
$src_x = ceil(($width - $new_width) * ($clamp[0] / 100));
$src_y = ceil(($height - $new_height) * ($clamp[1] / 100));
$dst = ImageCreateTrueColor($def_width, $def_height);
@ImageCopyResampled($dst, $src, 0, 0, $src_x, $src_y,
$def_width, $def_height, $new_width, $new_height);
Header("Content-type: image/".($make_png?'png':'jpeg'));
if ($make_png) {
ImagePng($dst);
if ($use_cache) {
ImagePng($dst, $thumb_file);
}
} else {
ImageJpeg($dst, null, 95);
if ($use_cache) {
ImageJpeg($dst, $thumb_file, 95);
}
}
@ImageDestroy($src);
@ImageDestroy($dst);
?>
I have a dynamic thumbnail script I found laying around the web and tweaked a bit. One of the things I added was a caching mechanism. Whenever a new thumb is generated, it is saved to disk, and the disk copy will be used if the same thumbnail (with all the same options) is requested again.
A snippet:
// name of cached file
$thumb_file = $_SERVER['DOCUMENT_ROOT'].'/thumbs/cache/'.
str_replace('/', '_', $_REQUEST['p']).
".{$def_width}x{$def_height}".
($clamp ? '_'.implode('x',$clamp) : '').
($make_png?'.png':'.jpg');
// get it from cache if it's there
if ($use_cache && file_exists($thumb_file)) {
Header("Content-type: image/".($make_png?'png':'jpeg'));
// this part seems really slow
$fp=fopen($thumb_file, "rb");
while (!feof($fp)) print fread($fp, 4096);
exit();
}
However, print
ing the result of fread
seems to be very slow, and sometimes (very rarely) the images don't load completely.
So, how can I speed this up? Should I just redirect the browser to the image instead of fread
ing it, or is there another option?
I'm including the full PHP script below, just in case.
<?php
$use_cache = $_REQUEST['nc'] ? false : true;
// $use_cache = false;
$upfile = $_SERVER['DOCUMENT_ROOT'] .'/'. $_REQUEST['p'];
$def_width = $_REQUEST["w"];
$def_height = $_REQUEST["h"];
$clamp = $_REQUEST['c'] ? explode("x",$_REQUEST['c']) : null;
$make_png = $_REQUEST['png'];
if (!file_exists($upfile)) {
die(); // $upfile = "nophoto.jpg";
}
if (!"{$def_width}{$def_height}") {
$def_width = $def_height = '100';
}
// name of cached file
$thumb_file = $_SERVER['DOCUMENT_ROOT'].'/thumbs/cache/'.
str_replace('/', '_', $_REQUEST['p']).
".{$def_width}x{$def_height}".
($clamp ? '_'.implode('x',$clamp) : '').
($make_png?'.png':'.jpg');
// get it from cache if it's there
if ($use_cache && file_exists($thumb_file)) {
Header("Content-type: image/".($make_png?'png':'jpeg'));
$fp=fopen($thumb_file, "rb");
while (!feof($fp)) print fread($fp, 4096);
exit();
}
$ext = strtolower(substr($upfile, -3));
ini_set('memory_limit', '64M');
if ($ext=="gif")
$src = @ImageCreateFromGif ($upfile);
else if ($ext=="jpg")
$src = @ImageCreateFromJpeg($upfile);
else if ($ext=="png")
$src = @ImageCreateFromPng($upfile);
$size = GetImageSize($upfile);
$width = $size[0];
$height = $size[1];
$long_side = $def_width;
if ($def_width < $def_height) $long_side = $def_height;
if (!$def_width) {
$factor_h = $height / $def_height;
$def_width = $width / $factor_h;
}
if (!$def_height) {
$factor_w = $width / $def_width;
$def_height = $height / $factor_w;
}
$factor_w = $width / $def_width;
$factor_h = $height / $def_height;
if ($factor_w > $factor_h) {
$new_height = floor($def_height * $factor_h);
$new_width = floor($def_width * $factor_h);
} else {
$new_height = floor($def_height * $factor_w);
$new_width = floor($def_width * $factor_w);
}
if ((!$clamp[0])&&$clamp[0]!=='0') $clamp[0] = 50;
if ((!$clamp[1])&&$clamp[1]!=='0') $clamp[1] = 50;
$src_x = ceil(($width - $new_width) * ($clamp[0] / 100));
$src_y = ceil(($height - $new_height) * ($clamp[1] / 100));
$dst = ImageCreateTrueColor($def_width, $def_height);
@ImageCopyResampled($dst, $src, 0, 0, $src_x, $src_y,
$def_width, $def_height, $new_width, $new_height);
Header("Content-type: image/".($make_png?'png':'jpeg'));
if ($make_png) {
ImagePng($dst);
if ($use_cache) {
ImagePng($dst, $thumb_file);
}
} else {
ImageJpeg($dst, null, 95);
if ($use_cache) {
ImageJpeg($dst, $thumb_file, 95);
}
}
@ImageDestroy($src);
@ImageDestroy($dst);
?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
函数
readfile
应该更快。如果您使用 PHP 作为 Apache 模块,您还可以查看
virtual
。The function
readfile
should be faster.If you are using PHP as an Apache module, you can also look into
virtual
.请用某些数字来定义“似乎”和“非常慢”。
否则只能用同样的术语来回答——“看来你可以粗略地得到一些东西”。
任何问“我怎样才能加快速度”的人应该首先回答这些问题:
根据我自己不太完美的测试,通过 PHP 提供图片比通过 Web 服务器本身慢 2 倍。我想说的是合理的,而不是“非常慢”。
因此,如果它运行“非常慢”,可能还有其他原因。就像这个缓存机制由于某些错误而根本不起作用一样。或者什么。在任何人都能提供帮助之前,需要进行一些分析以及调试。
特别是对于那些会尖叫“这不是答案!”的人。 (因为有一个愚蠢的假设,即答案只有直接且积极才算数),这里有一个供OP学习的链接:
http://shiftingpixel.com/2008/03/03/smart-image -调整大小/
相同的动态缩略图创建脚本,但具有“未修改”HTTP 缓存实现。
Please define "seems" and "very slow" in terms of certain numbers.
Otherwise there can be answers only in the same terms - "it seems you can roughly get something".
Anyone who is asking "How can I speed up" should answer to these questions first:
According to my own not-so-perfect tests, serving pictures via PHP is 2 times slower than via web-server itself. Reasonable I'd say, not "very slow".
So, if it runs "very slow" there could be some other reasons. Like this caching mechanism is not working at all due to some mistake. Or something. Some profiling, as well as debugging is required before anyone can help.
Especially for ones who will squeak "This is not an answer!" (because of that silly assumption that answer counts only it it's direct and positive), here is a link for the OP to learn from:
http://shiftingpixel.com/2008/03/03/smart-image-resizer/
a same on the fly thumbnail creation script but with " Not Modified" HTTP cache implementation.
如果您的网络服务器支持,
X-Sendfile
可能有助于加快速度。If your web server supports it,
X-Sendfile
might help speed things up.迁移到 PHP5。
PHP 4 有几个错误,导致所有形式的 fread 速度变慢并泄漏内存。根据您的描述,这听起来像是您所面临的情况。
升级,最好至少到5.3+
Move to PHP5.
PHP 4 had several bugs that caused all forms of fread to be slow down and leak memory. Based on your description, that's sounds like what you are up against.
Upgrade, preferably at least to 5.3+