通过“print fread(...)”提供图像很慢,该怎么办?

发布于 2024-09-15 02:04:05 字数 3622 浏览 4 评论 0原文

我在网上找到了一个动态缩略图脚本,并对其进行了一些调整。我添加的内容之一是缓存机制。每当生成新缩略图时,都会将其保存到磁盘,并且如果再次请求相同的缩略图(具有所有相同的选项),将使用磁盘副本。

片段:

  // 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, printing 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 freading 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

三生池水覆流年 2024-09-22 02:04:05

函数 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.

流云如水 2024-09-22 02:04:05

请用某些数字来定义“似乎”和“非常慢”。
否则只能用同样的术语来回答——“看来你可以粗略地得到一些东西”。

任何问“我怎样才能加快速度”的人应该首先回答这些问题:

  • 我想加快哪些特定操作
  • 目前需要多少时间。
  • 多长时间适合我。

根据我自己不太完美的测试,通过 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:

  • what certain operation I want to speed up
  • what certain amount of time it takes at the moment.
  • what certain amount of time will suit me.

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.

执着的年纪 2024-09-22 02:04:05

如果您的网络服务器支持,X-Sendfile 可能有助于加快速度。

If your web server supports it, X-Sendfile might help speed things up.

庆幸我还是我 2024-09-22 02:04:05

迁移到 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+

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文