tags:

views:

106

answers:

5

Hi, i made an image resizer in php. When an image is resized, it caches a new jpg file with the new dimensions. Next time you call the exact img.php?file=hello.jpg&size=400 it checks if the new jpg has already been created.

  1. If it has NOT been created yet, it creates the file and then prints the output (cool).
  2. If it ALREADY exists, no new file needs to be generated and instead, it just calls the already cached file.

My question is regarding the second scenario. Which of these is faster?

  1. redirecting: header('Location: cache/hello_400.jpg');die();
  2. grabbing data and printing the cached file: $data = file_get_contents('cache/hello_400.jpg'); header('Content-type: '.$mime); header('Content-Length: '.strlen($data)); echo $data;

Any other ways to improve this?

If someone wants the generated code, check this out: http://egobits.com/misc/img.phps

Thanks to all for the help!

+5  A: 

I would opt for never printing the data to the browser. Both scenarios should throw a permanent redirect to the generated image. Except if the image doesn't exist yet, it is created before the Location header is sent.

Edit:

Just to be clear about what I mean by permanent redirect...

header('HTTP/1.1 301 Moved Permanently'); 
header('Location: http://path/to/image'); 
Matt
to add to Matt, it can cache the image across the internet points from browser to proxy server.
Rohit
A: 

As a third (more powerful) option: cache the image in a binary field in a database, and query the database for it.

Implement all three solutions and benchmark them.

I'm going to guess that the first option (redirect) will be the slowest in the real world, because it requires just as much effort as the second option (file_get_contents), but involves a second request and more overhead.

Dolph
+3  A: 

Any other ways to improve this?

Yes.

There is a way to send nothing but just an HTTP header: a conditional get.
You can take a look at the similar script, http://shiftingpixel.com/2008/03/03/smart-image-resizer/, for the implementation

Col. Shrapnel
This worked perfectly. If the image doesnt exist, the script creates the new resized img and caches it. Next time you request the same link, the script serves the browser cached img. Thanks.
andufo
If someone wants the generated code, check this out: http://egobits.com/misc/img.phps
andufo
You may want to look into using readfile() instead of file_get_content because the the whole file is never loaded into php and gets sent directly to the user
Chris T
@ChrisT file_get_contents() is the preferred way to read the contents of a file into a string, so i guess readfile would not be the best way to go.
andufo
He doesn't need to load it into a string though, just output it to the browser
Chris T
+4  A: 

Maybe you could do the following:

  1. Set some directory for these images.
  2. Link to images in this directory (<a href="/img/resizable/hello_400.jpg>).
  3. Set your webserver to redirect to your php script if the image doesn't exist yet. If you are on Apache, a simple .htaccess will do. In PHP, you have $_SERVER["REQUEST_URI"] from which you can tell which image you should resize.
  4. Your script saves and echoes the image (but is called only for the first time).

This way, your get some benefits:

  • The image is cached (in a proxy or a browser) as any other static file.
  • PHP doesn't have to be called for every request just to redirect or output statical data.
  • You leave the implementation of If-modified-since and other cache-related headers to the webserver.
  • And the links look nicer :-)

Example .htaccess in your /img/resizable folder:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /img.php [L]
Krab
actually, _this_ is the correct answer
stereofrog
+1 I agree. Delegate to Apache as much as possible, only call PHP when it is actually needed.
Matt
A: 

If possible in your case, you can also implement a function to directly set the url of the cached image in your html like:

<img src="<?php getImageUrl('hello.jpg', 400); ?>" />

getImageUrl() will return the url of the cached image if it exists else it will return the url to dynamically generate the resized image.

Ramesh Tabarna