The proper way to "echo" and image?

How can I:

<?php
echo file_get_contents('calendar.gif');
?>

I guess my problem is probably needed to put headers, any help?
LVL 5
mnb93Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

TomeeboyCommented:
Little bit confused why you would want to use file_get_contents for this.. any particular reason?

I think you would normally just do this:

echo "<img src='calendar.gif'>";
mnb93Author Commented:
Yes but lets say that I want to open an image and then "echo" it.
I know how to include it in (x)html however this is different.
TomeeboyCommented:
file_get_contents will create a string of the binary contents of your image, which means echoing it will just spew out a bunch of binary code.  If you insist on using that method, you could create a PHP file that would output the image with the correct header:

header('Content-type: image/gif');
echo file_get_contents('calendar.gif');

Then call that file from an image tag src:

echo "<img src='getimage.php'>";

Or add support for multiple images and send the ID of the image in the query string (ex: getimage.php?id=1)

Something like that..
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Richard QuadlingSenior Software DeveloperCommented:
You are probably better off using fpassthru();


From the PHP Manual ...

<?php

// open the file in a binary mode
$name = './img/ok.png';
$fp = fopen($name, 'rb');

// send the right headers
header("Content-Type: image/png");
header("Content-Length: " . filesize($name));

// dump the picture and stop the script
fpassthru($fp);
exit;

?>


Rather than file_get_contents(). Mainly due to a waste of memory. If the image is a nice 118,000 pixel square of Orion, this COULD be a 24MG image (yep! I have one!).

Now with file_get_contents(), you are going to be actually loading that into the servers memory.

fpassthru() simply pushes the bytes to the browser.

A lot cleaner.
Richard QuadlingSenior Software DeveloperCommented:
If the image has been created using the image functions, then you can use ...

From the PHP Manual ...

<?php
if (function_exists("imagegif")) {
    header("Content-type: image/gif");
    imagegif($im);
} elseif (function_exists("imagejpeg")) {
    header("Content-type: image/jpeg");
    imagejpeg($im, "", 0.5);
} elseif (function_exists("imagepng")) {
    header("Content-type: image/png");
    imagepng($im);
} elseif (function_exists("imagewbmp")) {
    header("Content-type: image/vnd.wap.wbmp");
    imagewbmp($im);
} else {
    die("No image support in this PHP server");
}
?>

where in the above code, $im is the image resource created using the image functions.
alain34Commented:
may be a good idea is to use a class supporting already the 'echo' of an image and that also we provide you with additional transformation functionality.
2 for the price of 1.
Have a look at http://phpthumb.sourceforge.net/
mnb93Author Commented:
@You are probably better off using fpassthru();

Perfect except for one thing, I need the most optermised(fastest) way to add the mime type. (I am guessing that you would need to stuff round with the filename.
Because I know that I will be using PNG JP[E]G GIF.
Richard QuadlingSenior Software DeveloperCommented:
No matter what mechanism you use to get the bytes of the image to the client, you will ALWAYS need to supply the appropriate headers. This is essential.

The reason for fpassthru is local memory usage.

The appropriate headers will still need to be sent.

Maybe something like this ...

<?php
// /home/www/site/private is OUTSIDE of the webroot, which means users MUST use this program to access the images.
define ('IMAGE_LOCATION', '/home/www/site/private/images/');

// Has an file been asked for, does it exist, is it a picture and can we open it.
// You may want to use some sort of indexing mechanism rather than the real image name.
if (
      isset($_GET['imagename']) && 
      file_exists(IMAGE_LOCATION . $_GET['imagename']) && 
      (False !== ($am_image_data = @getimagesize(IMAGE_LOCATION . $_GET['imagename']))) &&
      (False !== ($fp_image = @fopen(IMAGE_LOCATION . $_GET['imagename'], 'rb')))
      )
      {
      // Send the appropriate mime header.
      header('Content-type: ' . $am_image_data['mime']);
      header('Content-length: ' . filesize(IMAGE_LOCATION . $_GET['imagename']);

      // Stream the image.
      fpassthru($fp_image);

      // Always exit.
      exit;
      }
else
      {
      // You may want to supply an image which contains the words "Image not found.".
      }
?>

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Richard QuadlingSenior Software DeveloperCommented:
The above code is not ultra secure. Personally I would add session control to only allow known users to access the images.

Say the above code is called getimage.php. You wouldn't want a script kiddie to come along with a little program guessing all the image names!

By using sessions, you first make sure you know who the user asking for the images is.

mnb93Author Commented:
Why is that code not secure? (Or are you only saying that because there is not authentication?
Richard QuadlingSenior Software DeveloperCommented:
Yes.

I could simply attempt to access ANY image by ...

http://www.site.com/getimage.php?imagename=guess1.jpg
http://www.site.com/getimage.php?imagename=guess2.jpg
http://www.site.com/getimage.php?imagename=guess3.jpg
http://www.site.com/getimage.php?imagename=guess4.jpg
http://www.site.com/getimage.php?imagename=guess5.jpg
http://www.site.com/getimage.php?imagename=guess6.jpg
http://www.site.com/getimage.php?imagename=guess7.jpg
http://www.site.com/getimage.php?imagename=guess8.jpg

If I come across the site which uses a php script to get the images without me being logged in, it probably would supply ALL the images without me being logged in.

But, the amount of effort in securing the script depends upon what is being protected.

You may not care! But just don't rely on that code for being THE most secure script in the world.

The main issue is that I've not tested the imagename value to make sure it is not attempting any nasty directory access.

But, as the image name has to exist as a file AND the file has to be an image AND the file has to be openable, this is probably secure enough.
mnb93Author Commented:
I don't care about authentication, but other things make up a secure script. eg. Proper Escaping...
mnb93Author Commented:
And is it just me or have has the font size gotten bigger for EE?
Richard QuadlingSenior Software DeveloperCommented:
If you are using Firefox, press CTRL+0 (zero). If you are using IE, try View|Text Size|Medium

You probably accidentally increased the font size whilst scrolling (if you have a wheel mouse).

CTRL+WheelDown increases the font size in both IE and FF.
Richard QuadlingSenior Software DeveloperCommented:
And that REALLY is off topic! But hey! I don't mind! <grin />
alain34Commented:
to overcome Rquadling isssue about security without using session, I'm using a key that is the MD5 of the image that I have saves in my database.
Two benefits. I'm not saving duplicate image in the database.
It is much more difficult to guess the image name!!!!!
http://www.conceptuel.co.uk/conceptCMS/image.php?id=52ac55a929f3416eec944d0005ee3aa8
mnb93Author Commented:
I know about the CTRL-0 I did that and I seems that the font on EE is one scrool too high. (After a CTRL-0)
Anyway...
"other things make up a secure script. eg. Proper Escaping..."

I will put in proper authentication...


Also:

"Two benefits. I'm not saving duplicate image in the database.
It is much more difficult to guess the image name!!!!!"

Two filenames can have the same MD5.
alain34Commented:
No, the MD5 of the binary representation of the image, not the MD5 of the file name, as they aren't any file name if you store the image in a database!!!
Richard QuadlingSenior Software DeveloperCommented:
Don't store the image in a DB!!!!!

Complete waste of time.

The DB cannot in any way process the "data" that is an image.

Use the disk to store the images as this is the best mechanism to use.

Imagine the SQL server serving up my 23MG of the Orion Nebula to 50 people or more. The amount of memory needed is HUGE! As the ENTIRE image would need to be extracted from the DB, sent to PHP, sent back to the webserver before being sent to the client.

Databases are for DATA.

Images are files. The filesystem is the place to manage files.

Sure, you can use an MD5 hash in a DB to join a hash to a name. Good way of doing things.

mnb93Author Commented:
Ok, weird I just logged-in and the font changed back to normal...
anyway, lol.... (Back on topic)

How bad would it be to extract the extension from the filename and use that for the MIME? (Yeah.. jpg => JPEG....)
Would that be faster than the other way?

Your thoughts and comments would be helpful.

@alain34 Probably just renaming the images to some random stuff would be better.... but meh...
mnb93Author Commented:
ohh... what!!! The fonts got bigger again... meh. dw EE is probably screwing round with their Stylesheets.
mnb93Author Commented:
And it's not me becuase if I navigate to some other site in the same tab, the fonts are normal....
mnb93Author Commented:
lol, The fonts are normal... (Yeah, I am on the verge of spamming but hey! (Anyone want vergara?))
mnb93Author Commented:
W00T the fonts stayed this time....
Richard QuadlingSenior Software DeveloperCommented:
The filename can be junk.

The mime type using getimagesize() is a GUARANTEE.

You should not see any real delay.

The image types that PHP knows about are within the first few bytes of the file.

I would use this.
Richard QuadlingSenior Software DeveloperCommented:
If you HAVE to provide the file via PHP (rather than just using <img src="somefile.jpg">) then you are not going to get much quicker than the code I provided.

mnb93Author Commented:
Ahh... beautiful!!!!!!!!!!!!!!! echo 'W'; while(true){echo '0';}echo 'T'; THE FONT IS BACK TO BIG!!! (dw though...)

And thanks for the info.

Steven
mnb93Author Commented:
BTW now the fonts are normal... (yeah..... I'll stop)
Richard QuadlingSenior Software DeveloperCommented:
<grin />
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.