Fetching an image from another server - php

Say, for this example, this is an image: http://www.basitansari.com/wp-content/uploads/logoaba.png which is hosted on website A.
I am calling this image into website B with an <img> tag. If the owner of site A removes this image then how can I know that the image has been removed using PHP? If the owner of site A removes the image then I want to show a notfound.jpg image. Should I use cURL for this purpose, or something else?

Checking the image server-side is definitely possible, but it may not be the best solution. Doing so means that all valid images will be loaded twice (once server-side and again by the client). A better method may be to use JavaScript to handle broken images. The following code will only take action if an error occurs while loading the image, replacing it with the image you specify:
<script type="text/javascript">
function brokenImage( obj ) {
obj.onerror = '';
obj.src = 'path/to/notfound.jpg';
return true;
}
</script>
<img onerror="brokenImage(this);" src="broken.jpg" alt="" />

if (!$fp = fopen('http://www.basitansari.com/wp-content/uploads/logoaba.png', 'r')) {
// The image cannot be retrieved, handle it here.
} else {
fclose($fp);
}
This is the quickest way as it just checks that the image can be successfully retrieved, it doesn't download the whole file.

You should call that URL with HEAD method and check if status code 404 (Not found) or 200 (OK)

You can call directly: Check if image source exists using fopen and if not show notfound.jpg. # is used to supress warning
<img src="<?php if (#fopen("http://www.basitansari.com/wp-content/uploads/logoaba.png", "r")) {echo 'http://www.basitansari.com/wp-content/uploads/logoaba.png';} else{echo 'notfound.jpg';}?>" />

Related

Show image based on access privilege

I am trying to display img_a.png or img_b.png based on the access level of the user (e.g. signed in or not). Of course the content (in this case img_a and img_b) should not be available to the general public.
I tried a few solutions, none of them helps me and that's why I look for help here. What I tried so far is:
Based on the user checks I tried adding the resources folder to "open_basedir" which is a lame option but was looking the easiest solution. All ended up by raising a warning that resource is not in the basedir folder through it's obviously there.
Attempted to put the resources in the public folder and restrict them via .htaccess. But in this case they got restricted not only for the unwanted audience but for everyone.
Final and closest attempt was to put back the images outside the webroot and write a class that validates the access and serves the image like:
class Image {
...
public function getImage() {
...
header('Content-Type: '.$this->type);
readfile($this->item);
which afterwards is displayed in the initial script through:
echo "<img src=".$image->getImage($file).">";
The problem above is that the headers were already sent so I could either stream the image or the html output of the .php page but not both. Do I have a way out there?
Create a script that checks whatever user attribute you want, determines what image to serve, and read/send that image. Use the script URL as the <img src=... attribute, ie
<img src='/scripts/user_image.php'>
Something like this will work for PNG images. Similar functions exist for GIF, JPG, etc.
<?php
// do stuff here to determine file name of image to send
if($_SESSION['userlevel']=="ADMIN"){
$imageFilename="admin_image.png";
}
// Create Image From Existing File
$image = imagecreatefrompng($imageFilename);
//Set the Content Type
header('Content-type: image/png');
// Send Image to Browser
imagepng($image);
// Clear Memory
imagedestroy($image);
exit;
?>
OK, per your comment, I think you are referencing things wrong.
My working script is exact as above, only the if-then is commented out. I'm just assigning the filename to the variable. I've named the script user_image.php.
A simple index.html file to reference the image -
<html>
<head><title>test</title></head>
<body>
Hello World!<br />
<img src="user_image.php">
</body>
</html>
And it Just Works. See it in action at https://itsjustcrap.com/img or grab source at https://itsjustcrap.com/img/src.zip
I'll leave it up for a few days, but other than a png image and a commented out if-then, the source is exact same as what is in this post.
Actually I think I found a solution to the headers confict I had.
Displaying the image as data like:
<img src="data:image/png;base64, <?=base64_encode(file_get_contents($file))?>" alt="img">
instead of feeding it inside the source attribute with readfile() php script like:
<img src="image.php?<?=$file?>" alt="my_image">
where the last one was giving me a headers conflict when inside html page.
Discovered the solution over here How to display Base64 images in HTML?

How do I get a default picture when a picture errors

I am trying to get a picture from the database and echo this on my website, and everything works like I want to, but now I got this tiny problem where if the image has no name yet, or it errors (like a 404 error), that I get a ugly tiny broken image icon.
Can I get it to work that I get a default image when I get the error? I tried this, but it only worked for where there was no name set yet.
if(!empty($filename)){ echo $filename;} else{ echo "pf.png"; }
Insert this in the image tag:
onerror="this.src='[img src]'"
Since you say it is working with "pf.png", I assume that you are at least using the filename correctly. So if you get that broken image, it means the resource could not be loaded, because it does not exist or cannot be retrieved.
So you also have to check that the image exists before trying to use it anyhow :
if(!empty($filename) && file_exists($filename) {
echo $filename;
} else {
echo "pf.png";
}
To do this i php, you will have to check if the file exists. You wont be able to do this if the link to the image is over "http:/www.*"
Clément Malet code above works fine.
You can read more about file_exitsts function here:
http://php.net/manual/en/function.file-exists.php
If the link to image is over "http:/www.*" you can use jquery.
Put this code before </body> Remember to include jquery
$(document).ready(function(){
$("img").error(function(){
$(this).attr("src", "http://google.dk/default.php");
})
.each(function() {
$(this).attr("src",$(this).attr("src"));
});
})

php delete image from server after upload & display

Sending an image in my php form, it gets saved onto my server and at the
action.php page it gets displayed. Now when I try to:
echo '<div id="image"><img src="'.$target_path.'" width="280" height="280"></div>';
it works just fine... but if I add unlink($target_path); at the end of my php code it
will not even display the image even though it gets deleted AFTER displaying the image...
So the question is, how can I display the image and deleting it at the same time so my server does not gets stuffed with user pictures?
Try another thing: output the image base-64 encoded.
$contents = file_get_contents($file);
$base64 = base64_encode($contents);
echo '<div id="image"><img src="data:image/jpg;base64,'.$base64.'" width="280" height="280"></div>';
(instead of move_uploaded_file() etc, use as $file variable the $_FILES[...]['tmp_name'])
You can achieve this by creating a little script that gets the image-filename and will delete it after it has been retrieved:
<?php
$file = image_file_from_parameter($_GET['image']);
headers_for_file($file);
readfile($file);
unlink($file);
In your HTML output you then link to that script:
<img src="path/to/image.php?image=893sudfD983D" />
If you set nice caching headers, the user won't notice that your server did serve the file only once.
When you echo the url of an image with img src you're just sending the browser the url of an image, not the actual image data. The image needs to remain on the server if you want it to be viewable by this approach.
You could use bwoebi's solution to pass the actual image data instead of a link, but a better solution is just to keep the images on the server and periodically delete old files.

how to send png image from server to display in browser via ajax

I have been having a hard time with what must be an incredibly normal task. I upload and save images to my web server and save the path to the file in MySQL data base (this is all working). The thing that doesn't work is fetching an image file from the server and displaying it on the page via ajax.
Originally I was trying to just retrieve the path from the database, and update an tag's src attribute with the path to the image. This was working, but this way all the images are in a folder on the server where people all have access to them. This is not good. I can only have the pictures that belong to certain users accessible by these users.
In order to restrict access to these photos I added an Apache directive on that folder, which successfully restricted access. The problem then became that I could not display the images in the browser by setting the src attribute to that path. See my post: https://serverfault.com/questions/425974/apache-deny-access-to-images-folder-but-still-able-to-display-via-img-on-site
Finally I have learned that I have to use PHP to read the image data directly from the server and send this data to the browser. I have used the file_get_contents() function, which works to convert the image file (PNG) on the server into a string. I return this string to the browser in an ajax call. The thing I can't get is: how to convert this string back into an image using JavaScript?
See this code:
$.ajax({
url: get_image.php,
success: function(image_string){
//how to load this image string from file_get_contents to the browser??
}
});
You could display a default "no access" image to users who are forbidden to access the image:
<?php
$file = $_GET['file']; // don't forget to sanitize this!
header('Content-type: image/png');
if (user_is_allowed_to_access($file)) {
readfile($file);
}
else {
readfile('some/default/file.png');
}
And, on the client side:
<img src="script.php?file=path/to/file.png" />
Alternatively, if you really really want or need to send the data via Ajax, you can Base64 encode it:
<?php
echo base64_encode(file_get_contents($file));
And place the response in an img tag using the Data URI scheme
var img = '<img src="data:image/png;base64,'+ server_reponse +'"/>';
Given that the Base64 encoded data is significantly larger than the original, you could send the raw data and encode it in the browser using a library.
Does that make sense to you?
Instead of getting get_image.php through AJAX, why not just use:
<img src="get_image.php" />
It's practically the same thing. You can just use AJAX to update the <img> dynamically.
You can't do it via ajax.
You could do something like this:
<img src="script.php?image=image_name" />
Then use JavaScript to change the query string.
You can actually embed image data inside the img tag in the browser, therefore ajax code could look like this:
$.ajax({
url: get_image.php,
success: function(image_string){
$(document.body).append("<img src='data:image/gif;base64," + base64_encode(image_string) + "' />);
}
});
Note that you will need to write this base64_encode function. Have a look at this question - the function is given there.

Ajax image grabber

I need an image grabber. By that I mean a Digg like image grabber that can search other pages (including youtube, normal websites, economist,...whatever), get the images that are of decent sizes and if I select it, I can upload it to my server.
Does anyone know of a plugin for this?
Thanks.
I don't know about any off-the-shelf library. But I once needed a quick way to retrieve the "main image" off a page. My best guess was to just get the largest in file size. I was using the PHP SimpleHTMLDom library for easy access to the site's <img> tags.
Now, here's the main part of the code, that returns the URL of the biggest image file for a given page.
Hope you can build on that.
// Load the remote document
$html = file_get_html($url);
$largest_file_size=0;
$largest_file_url='';
// Go through all images of that page
foreach($html->find('img') as $element){
// Helper function to make absolute URLs from relative
$img_url=$this->InternetCombineUrl($url,$element->src);
// Try to get image file size info from header:
$header=array_change_key_case(get_headers($img_url, 1));
// Only continue if "200 OK" directly or after first redirect:
if($header[0]=='HTTP/1.1 200 OK' || #$header[1]=='HTTP/1.1 200 OK'){
if(!empty($header['content-length'])){
// If we were redirected, the second entry is the one.
// See http://us3.php.net/manual/en/function.filesize.php#84130
if(!empty($header['content-length'][1])){
$header['content-length']=$header['content-length'][1];
}
if($header['content-length']>$largest_file_size){
$largest_file_size=$header['content-length'];
$largest_file_url=$img_url;
}
}else{
// If no content-length-header is sent, we need to download the image to check the size
$tmp_filename=sha1($img_url);
$content = file_get_contents($img_url);
$handle = fopen(TMP.$tmp_filename, "w");
fwrite($handle, $content);
fclose($handle);
$filesize=filesize(TMP.$tmp_filename);
if($filesize>$largest_file_size){
$largest_file_size=$filesize;
$largest_file_url=$img_url;
unlink(TMP.$tmp_filename);
}
}
}
}
return $largest_file_url;

Categories