How to find out extension of a file through its url? - php

I am trying to find out what extensions a particular url has, Here is what I am trying to do:
$pathinfo = pathinfo('http://imgur.com/9P54j');
$extension = $pathinfo['extension'];
echo $extension;
The url 'http://imgur.com/9P54j' is actually a url having 9P54j.gif image, and its not evident in the url, how do I extract the extension .gif of the the file '9P54j' ?

That URL is not a URL to the .gf image, but a page that contains the image in its HTML. You will want to parse the HTML for the URL to the image. Try: rightclick on the image in the link you provided above, and click "open image" or "view image" to see the full URL.
Even that URL may not have an extension because the data may be streamed to the user bia PHP. If that's the case, just check the Content-Type header to find out what the extension is.

You can use a regex to extract it, something like this:
$url = 'http://imgur.com/9P54j';
$content = file_get_contents($url);
$explode = explode('/', $url);
preg_match('/http:\/\/i\.imgur\.com\/' . array_pop($explode) . '(\.[A-z]{1,4})/', $content, $matches);
$ext = $matches[1]; // '.gif'

My answer assumes that would like to grab the file's extension from urls that have no extensions in the url itself.
Using pathinfo() will not work as it retrieves the extension using text procession and in the url there is just no extension.
An approach would be to use lower level http functionality that allows to send a http request to the url and fetch the response headers. The response headers should regulary contain the 'Content-Type:' header that shows us the mimetype of the content.
Once having the 'Content-Type' header you could use a translation table and translation mimetype to file extension. This list of supported extensions would of course be limited und there are mimetypes that can translate to more than one extension. In such cases you would have to do further investigations on the files content itself.
As a real php programm would be too large for this answer I'll give just a pseudo code:
<?php
function get_extension_from_mimetype($url) {
// static translation table. to be extended
static $translationTable = array (
'image/jpeg' => 'jpg',
'text/xml' => 'xml',
'text/html' => 'html'
);
$defaultExtension = 'dat';
// you'll have to write this method
$mimetype = get_mimetype_by_url($url);
if(isset($translationTable[$mimetype])) {
$extension = $translationTable[$mimetype];
} else {
$extension = $defaultExtension;
}
return $extension;
}

Related

Outputting image using php

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.

Show image from other domain without showing the domain name - PHP

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');

Get file extension while using file_get_contents() in PHP

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);

PHP get image extension from url?

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

How to get a file extension from a file name without extension?

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.

Categories