tags:

views:

1280

answers:

5

Hi,

i want to monitor how often some external images are loaded. So what my idea was instead of giving a uri directly like this:

www.site.com/image1.jpg

i create a php script which reads the image, so i build a php file and my html would look like this:

<img src="www.site.com/serveImage.php?img=image1.jpg">

but i don't know how to read the image from disk and return it. Would i return a byte array, or set the content type?

Kind regards, Michel

A: 

You must set the content type:

header("Content-type: image/jpeg");

Then you load the image and output it like this:

$image=imagecreatefromjpeg($_GET['img']);
imagejpeg($image);
mck89
imagecreatefromjpeg + imagejpeg might be a bit overkill (anc CPU-consumming) if you just want to send the data from a file -- advantage I see is making sure you really load image ; but there are probably other ways to be sure of that (like allowing only one directory, that only contains images)
Pascal MARTIN
readfile is better if you are just gonna send the image as is.
OIS
+6  A: 

To achieve something like this, your script will need to :

  • send the right headers, which depend on the type of the image : image/gif, image/png, image/jpeg, ...
  • send the data of the image
  • making sure nothing else is sent (no white space, no nothing)

This is done with the header function, with some code like this :

header("Content-type: image/gif");

Or

header("Content-type: image/jpeg");

or whatever, depending on the type of the image.


To send the data of the image, you can use the readfile function :

Reads a file and writes it to the output buffer.

This way, in one function, you both read the file, and output its content.


As a sidenote :

  • you must put some security in place, to ensure users can't request anything they want via your script : you must make sure it only serves images, from the directory you expect ; nothing like serveImage.php?file=/etc/passwd should be OK, for instance.
  • If you're just willing to get the number of times a file was loaded each day, parsing Apache's log file might be a good idea (via a batch run by cron each day at 00:05, that parses the log of the day before, for instance) ; you won't have real-time statistics, but it will require less resources on your server (no PHP to serve static files)
Pascal MARTIN
thanks for the sidenote: •you must put some security in place, to ensure users can't request anything they want via your script : you must make sure it only serves images, from the directory you expect ; nothing like serveImage.php?file=/etc/passwd should be OK, for instance.
Michel
+3  A: 

You're probably better off examining your server access logs for this. Running all images through php might put a bit of load on your server.

nickf
hmm, that would surely do the trick. i'll save that when the load becomes an issue.
Michel
In addition, running them through a PHP script will affect client-side caching, which could in fact increase the read load.
Rob
@rob: that has nothing to do with running it through a script, but forgetting to send the right headers. I have the 2 best ones in my answer.
OIS
+4  A: 

Sending images through a script is nice for other things like resizing and caching on demand.

As answered by Pascal MARTIN the function readfile and the following header are the requirements.

  • Content-Type
    • The mime type of this content
    • header('Content-Type: image/gif');
    • Types
      • image/gif
      • image/jpeg
      • image/png

But beside the obvious content-type you should also look at other headers like

  • Content-Length
    • The length of the response body in octets (8-bit bytes)
    • header('Content-Length: 348');
    • See the function filesize
    • Allows the connectio to be better used.
  • Last-Modified
    • The last modified date for the requested object, in RFC 2822 format
    • header(Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT');
    • See the function filemtime
    • You can exit the script after sending a 304 if the file modified time is the same.
  • status code
    • header("HTTP/1.1 304 Not Modified");
    • you can exit now and not send the image one more time

For last modified time, look for this in $_SERVER

  • If-Modified-Since
    • Allows a 304 Not Modified to be returned if content is unchanged
    • If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
    • Is in $_SERVER with the key http_if_modified_since

List_of_HTTP_headers#Responses

OIS
+2  A: 

Also, if you want to the user to see a real filename instead of your scriptname when the user RMC's on the image and selects "Save As", you'll need to also set this header:

header('Content-Disposition: filename=$filename');
this can also be solved with redirecting in apache (virtual host or .htaccess) to the script file. so /img/somefile_small.jpg get internal redirect to showimage.php
OIS