通过 `print fread(...)` 提供图像很慢,该怎么办?
Posted
技术标签:
【中文标题】通过 `print fread(...)` 提供图像很慢,该怎么办?【英文标题】:Serving images via `print fread(...)` is slow, what to do? 【发布时间】:2010-08-15 02:11:39 【问题描述】:我在网上找到了一个动态缩略图脚本,并进行了一些调整。我添加的其中一件事是缓存机制。每当生成新的缩略图时,它都会保存到磁盘,如果再次请求相同的缩略图(具有所有相同的选项),则将使用磁盘副本。
一个sn-p:
// name of cached file
$thumb_file = $_SERVER['DOCUMENT_ROOT'].'/thumbs/cache/'.
str_replace('/', '_', $_REQUEST['p']).
".$def_widthx$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();
但是,print
fread
的结果似乎很慢,有时(很少)图像无法完全加载。
那么,我怎样才能加快速度呢?我应该将浏览器重定向到图像而不是fread
ing,还是有其他选择?
我在下面包含了完整的 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_widthx$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);
?>
【问题讨论】:
【参考方案1】:函数readfile
应该更快。
如果您使用 PHP 作为 Apache 模块,您还可以查看virtual
。
【讨论】:
哇几乎同时发帖。 @Null 都说 2010-08-15 02:13:45Z。我们需要在这里完成照片:p【参考方案2】:请用某些数字来定义“似乎”和“非常慢”。 否则只能用相同的术语给出答案——“似乎你可以大致得到一些东西”。
任何问“我怎样才能加快速度”的人都应该首先回答这些问题:
我想加快什么操作 目前需要多少时间。 什么时间适合我。根据我自己不太完美的测试,通过 PHP 提供图片比通过网络服务器本身慢 2 倍。我会说是合理的,而不是“非常慢”。 因此,如果它运行“非常慢”,可能还有其他一些原因。像这种缓存机制由于某些错误而根本不起作用。或者其他的东西。一些分析,以及调试是需要在任何人可以帮助之前。
特别是对于那些会尖叫“这不是答案!”的人。 (因为那个愚蠢的假设,即答案只计算它是直接的和肯定的),这里有一个链接供 OP 学习:http://shiftingpixel.com/2008/03/03/smart-image-resizer/ 一个相同的动态缩略图创建脚本,但具有“未修改”的 HTTP 缓存实现。
【讨论】:
它太慢了,足以让我在 SO 上询问它。我想我可以用javascript或wireshark之类的东西来测试它,但我希望这是一个足够常见的问题,其他人已经知道答案了。顺便说一句,我认为您在缓存标头方面走在了正确的轨道上;感谢您的链接。 @no 这不是一个常见的问题。治愈有帮助,但你仍然不知道疾病 我怀疑它可能与内容长度标头不存在有关。我真的没有太多时间花在这样的小问题上;通过 304 使用浏览器缓存对我来说已经足够了。【参考方案3】:如果您的网络服务器支持它,X-Sendfile
可能有助于加快速度。
【讨论】:
【参考方案4】:迁移到 PHP5。 PHP 4 有几个错误导致所有形式的 fread 变慢并泄漏内存。根据您的描述,这听起来像是您遇到的问题。
升级,最好至少到5.3+
【讨论】:
以上是关于通过 `print fread(...)` 提供图像很慢,该怎么办?的主要内容,如果未能解决你的问题,请参考以下文章