0

I have a website with images upload/show functionality on it. All images are saved into filesystem on a specific path.

I use Yii2 framework in the project. There isn't straight way to the images and all of them requested by specific URL. ImageController proceses the URL and takes decision about image resizing. ImageModel does the job. The user get image content.

Here the code snippet:

$file = ... // full path to image
...
$ext = pathinfo($file)['extension'];

if (file_exists($file)) {
    // return original
    return Imagine::getImagine()
        ->open($file)
        ->show($ext, []);
}

preg_match("/(.*)_(\d+)x(\d+)\.{$ext}/", $file, $matches);
if (is_array($matches) && count($matches)) {
    if (!file_exists("{$matches[1]}.{$ext}")) {
        throw new NotFoundHttpException("Image doen't exist!");
    }

    $options = array(
        'resolution-units' => ImageInterface::RESOLUTION_PIXELSPERINCH,
        'resolution-x' => $matches[2],
        'resolution-y' => $matches[3],
        'jpeg_quality' => 100,
    );

    return Imagine::resize("{$matches[1]}.{$ext}", $matches[2], $matches[3])
        ->show($ext, $options);
} else {
    throw new NotFoundHttpException('Wrong URL params!');
}

We don't discuss data caching in this topic.

So, I wonder about efficient of this approach. Is it ok to return all images by PHP even they aren't changed at all? Will it increase the server load?

Or, maybe, I should save images to another public directory and redirect browser to it? How long does it take to so many redirects on a single page (there are can be plenty images). What about SEO?

I need an advice. What is the best practice to solve such tasks?

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
GHopper
  • 366
  • 4
  • 15

1 Answers1

2

You should consider using sendFile() or xSendFile() for sending files - it should be much faster than loading image using Imagine and displaying it by show(). But for that you need to have a final image saved on disk, so we're back to:

We don't discuss data caching in this topic.

Well, this is actually the first thing that you should care about. Sending image by PHP will be significantly less efficient (but still pretty fast, although this may depend on your server configuration) than doing that by webserver. Involving framework into this will be much slower (bootstrapping framework takes time). But this is all irrelevant if you will resize the image on every request - this will be the main bottleneck here.

As long as you're not having some requirement which will make it impossible (like you need to check if the user has rights to see this image before displaying it) I would recommend saving images to public directory and link to them directly (without any redirection). It will save you much pain with handling stuff that webserver already do for static files (handling cache headers, 304 responses etc) and it will be the most efficient solution. If this is not possible, create a simple PHP file which will only send file to the user without bootstrapping the whole framework. If you really need the whole framework, use sendFile() or xSendFile() for sending file.

The most important things are:

  1. Do not use Imagine to other things than generating an image thumbnail (which should be generated only once and cached).
  2. Do not link to PHP page which will always only redirect to real image served by webserver. It will not reduce server load comparing to serving image by PHP (you already paid the price of handling request by PHP) and your website will work slower for clients (which may affect SEO) due to additional request required to get actual image.
  3. If you need to serve image by PHP, make sure that you set cache headers and it works well with browser cache - you don't want to download the same images on every website refresh.
rob006
  • 21,383
  • 5
  • 53
  • 74
  • I think you are right! So, I should create public directory and keep there all images as static files. But I don't realize how to avoid redirections due to user can request any image parameters in any time. That is why I can't prepare the file until I get specific request. And in other side, the browser can't handle the request becouse file doesn't exists yet. So, how to know which file I have to put in the directory without reques->redirection->new_request chain? – GHopper Jul 29 '18 at 07:55
  • 1
    You may try this approach: https://stackoverflow.com/a/49712207/5812455 - you can create URL rule which will catch request for non-existent images. In this way requests for existing images will be handled by webserver, and requests for new images will be redirected to PHP, so you will be able to generate thumbnail and save it at requested URL. Next request for this URL will be handled by webserver, so PHP will be involved only in first request. – rob006 Jul 29 '18 at 09:11