There are a bunch of questions of with the same title as this one.
For instance
How to output images using php?
Output as an image using PHP
How to output image and download using php
Invariably the answer is some variation of
add header('Content-type: image/jpeg'); to your code
Which is an important part of the answer, no doubt, but leaves out some vital steps I really cannot work out.
Now, there is obvious benefit to fetching an image using php when the image is situated below the root directory.
So suppose you have a web page
<?php
require_once("load_a_scripts.php");
print("lots of html");
// fetch image from below root directory and output in HTML
?>
<img id="this_one" src="" height="200" width="200" />
And you want to output the image this_one, above?
PHP can be used to fetch the required file using readfile(), but that will not be terribly useful here (at best you will get random unicode output instead of a proper image here).
The solution to prevent garbled output is to use
header('Content-type: image/jpeg');
This clearly seems inappropriate here. Not only is there output, which would make setting the header impossible, but even if this course of action is successful, the best that one can hope for is a download prompt for the image. Again, this is not desired functionality.
So some solutions suggest some external code, like "image.php" that will have its own header and will fetch the image, and so on. However, there's again some issues with this.
How will image.php know what what image it is you want?
<?php header('Content-Type:'.$photo);
if(isset($photo)&&isset($type)){
if(strlen($photo)>15||strlen($type)>6){
die();
}
$photo = strtolower($photo);
$photo = preg_replace('/[^a-z0-9 -]+/', '', $photo);
$photo = str_replace(' ', '-', $photo);
$photo = trim($photo, '-');
$type = strtolower($type);
$type = preg_replace('/[^a-z0-9 -]+/', '', $type);
$type = str_replace(' ', '-', $type);
$type = trim($type, '-');
readfile('../img/'.$user_id.$photo);
}
The parameters relating to the image name ($photo) and mime ($type) can hypothetically be sent using GET, but again, what sends these parameters, and how?
Some answers seemed to indicate that you could directly link to the external image.php as if it were an image
<img src="image.php" />
But this again raises the question about how image.php knows what the values for $photo and $type.
You have two basic options: first, using an external image-loader/handler script (e.g. <img src="image.php?i=sunshine.jpg" />); second, base64-encoding the image data (e.g. <img src="data:image/png;base64, i26dfdXAd..." />). The second option will make your HTML bloat like there's no tomorrow. So let's simply look at the image.php handler approach.
How does the handler know what image to show? It'll need a query string, e.g. image.php?i=sunshine.jpg; or image.php?i=sunshine&x=jpg; or image.php?i=sunshine&x=jpg&s=600, if you wanted to load a particular size, and so on. You will have to use that format in your HTML source, there's no script that would automagically know what image to load. Then, it's "who" (you), not "what", that sends the parameters. You'll want to make sure that the variables are properly sanitized (as your sample handler is doing); like any user-modifiable input, they shouldn't be trusted, especially anywhere near filesystem operations (directory traversal, etc.). These variables will be available as $_GET['i'], $_GET['x'], etc. to your handler script.
If you feel like URL parameters are a hassle, or just look dirty, you could always rewrite URLs. Link an image as <img src="images/sunshine.jpg" />, and have a .htaccess rewrite rule in place in the /images/ folder (containing only your script) that passes all image requests to your handler script. See the "htaccess redirect all images to handler" Q/A for an example. You could also use this approach for handling down-scaled image versions, with source URLs like <img src="images/sunshine__600.jpg" /> mapped to a rewrite rule.
On the use of readfile() (the most memory-friendly way of blurting out large chunks of data), as long as you output the header('Content-type: image/jpeg'); (or other appropriate MIME header) before your readfile() call, it will work in the desired way. That is to say, browser won't know the difference between images served directly from the filesys by the webserver, or images served from outside the webroot with a handler. It's just data with an image HTTP header.
Edit: Bonus. Coded a minimalist safe-to-deploy file-handler.
<?php
/*
* Receive image call as: <img src="img.php?i=name.jpg" />
* Output matching image file from $basepath directory
*/
$basepath = '../images/'; // Path to image folder
$mimes = [ // Allowed image types:
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'svg' => 'image/svg+xml',
];
!isset($_GET['i']) && die(); // Nothing to do here.
// Parse & Verify Extension
$ext = strtolower(pathinfo($_GET['i'], PATHINFO_EXTENSION));
!isset($mimes[$ext]) && die('Invalid filetype!'); // If MIME N/A: die!
// Parse & Sanitize Filename
$file = basename($_GET['i']);
$file = preg_replace('#[^[:alnum:] ._-]#', '', $file);
$filepath = realpath($basepath . $file);
$filepath === false && die('Invalid filename!'); // If image N/A: die!
// Output MIME header and image:
header('Content-Type:' . $mimes[$ext]);
readfile($filepath);
exit;
If you need to accommodate jpeg etc. variants, simply a) duplicate the MIME definitions in the $mimes array, or b) add an extension normalization routine. If you need to access images in subfolders, e.g. ?i=sun/shine.jpg, rework the filename parse/sanitize routine without basename. (Be sure you're safe from directory traversal!). Characters other than [:alnum:] ._-] are removed from the requested filename. Modify the regex as necessary.
I want to show an image on my website but not want to save in on my hosting.
I want to show it something like this:
<img src="https://example.com/img/pic.jpg">
or
<img src="https://example.com/img/image.php?img=pic.jpg">
Instead of:
<img src="https://example.org/img/pic.php">
I have tried using PHP file_get_contents() and CURL etc but none of that works.
This below codes have worked which convert image from URL to data:image but it takes too much time to load.
$url = 'https://otherdomain.com/img/'.$_GET['img'];
$allow = ['gif', 'jpg', 'png']; // allowed extensions
$img = file_get_contents($url);
$url_info = pathinfo($url);
// if allowed extension
if(in_array($url_info['extension'], $allow)) {
// Format the image to data:image : data:{mime};base64,{img_data_base64};
$re = 'data:image/'. $url_info['extension'] .';base64,'. base64_encode($img);
}
else $re = 'Invalid extension: '. $url_info['extension'];
header('Content-Type: application/json');
echo json_encode($src); // output $re data
I want proper URL format as I have mentioned above(https://example.com/img/image.php?img=pic.jpg) without saving image on my server.
NOTE: Here https://example.com is my domain but https://example.org is not.
Thanks
You can try this,
Your php page url - https://example.com/img.php?img=abc.png;
img.php code (You can change image path or url as per you)
think image url https://picsum.photos/id/666/536/354 as another domain https://example.org in your case
header('Content-Type: image/png');
readfile('https://picsum.photos/id/666/536/354');
Im retrieving images from thee google places API on my PHP server by using the following lines of code
$response = file_get_contents($url);
I'm also writing this file onto a folder on the server like so: (The file returned is a binary file, not an image file)
file_put_contents($folderPath,$response);
How do I find out the file extension of the file I read into $response?
I have tried the following:
$response = file_get_contents($url);
$size = getimagesize($response);
$extension = image_type_to_extension($response)
Google wont return a file with a suffix. Try mime_content_type($response) and then parse the response to figue out the correct suffix
try pathinfo
http://php.net/manual/en/function.pathinfo.php
it should help you
[EDIT]
Since your image is returned as binary, then use php's getimagesizefromstring http://php.net/manual/en/function.getimagesizefromstring.php
It will return all the details you need.
You can use pathinfo to get the extension.
$extension = pathinfo($response, PATHINFO_EXTENSION);
Image url like below.
$url = https://lh3.googleusercontent.com/-4T303dPCnp0ZnkzQjSIjeB7k8L_DiQglhUgNqXM-OkeLQXoNwwFnzM1MoFjJGw7DGI=w300
How to get extension from this url.
I m using pathinfo to get extension but it's not work
$ext = pathinfo($destinationPath.$filename, PATHINFO_EXTENSION);
Anyone help me to get image extension from url.
pathinfo just parses a path, you can't use it in this context, when path doesn't have extension in it. You need to assign extension based on mime type.
So, first, get mime type, like here: https://stackoverflow.com/a/12023961/1059672
Then, assign extension based on mime type, like here: https://stackoverflow.com/a/16511092/1059672
PHP: I am uploading image files in a folder with a name of particular format which is like postid_posttype_postserial.ext so that while showing particular blog post I would just use this format based on the post id, post type of that post. But problem here is I dont have extension of that file. So here is the actual question, how do I get the extension of a file of which I just know the name(in name.ext) not the extension.
FYI I searched for this and I found few function which returns extensions but you have to pass a full filename that is with extension to get the info about the file.
In your case, you need to get the mime type of the file then do a switch statement in PHP. You can get the mime type of the file by:
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$mime_type = finfo_file($finfo, $postid_posttype_postserial_file);
finfo_close($finfo);
$mime_types = array(
'image/gif' => '.gif',
'image/jpeg' => '.jpg',
// etc.
);
$ext = array_key_exists($mime_type, $mime_types) ? $mime_types[$mime_type] : false;
echo $ext;
Learn more: http://www.php.net/manual/en/function.finfo-file.php
Update 2: As pointed out by the comment, replacing switch to array matching is more elegant.