
|
View Full Version : Replace image file if not found in external server
latheesan 12-28-2005, 07:05 PM Hello,
Im building a topsites script for my site. If a member submit their site details, the banner url is stored in the field "banner" in the db.
When i display the records of topsites from db, i want to replace any images that doesnt exist or doesnt work with my own.
for e.g.
$banner = "http://www.site.com/images/banner77.gif";
how can i test to see, if the url in the string $banner actually does exist, if not replace it with my own image ?
01globalnet 12-28-2005, 11:07 PM $handle = fopen($banner_from_db, "r");
if ($handle) {
$banner = $banner_from_db;
} else {
$banner = $banner_default;
}
fclose($handle);
If the banner is a full url from external site this will result to slower loading of your pages - it is recommended to make the check when the users submit their sites.
Burhan 12-29-2005, 03:35 AM You could check the response that is sent from the server on the request. If the file doesn't exist, you'll get 404. For this to work, you don't need to fetch the entire file, just fetch the first few bytes to get the headers.
There are quite a few scripts on the net that do this already. Just google to find out.
latheesan 12-29-2005, 07:37 AM tonyFF --->>> very nice suggestion. Im going to try using urs until i find a substitute on google, like fyrestrtr mentioned.
Thanks both of u.
latheesan 12-29-2005, 07:46 AM Fyrestrtr, is this how to check for reponse from server?
<?php
if(headers_sent($file, '404')) {
echo "Image exist";
} else {
echo "Image does not exist";
}
?>
Could i use this method instead, because i couldnt get the above to work?
<?php
$filename = '$banner';
if (file_exists($filename)) {
echo "The file $filename exists";
} else {
echo "The file $filename does not exist";
}
?>
Burhan 12-29-2005, 10:14 AM file_exists only works on local files (unless you are using PHP 5.0 and above).
The easy way to find out if an image exists on a remote server is to make a connection to it, send a request, and read the first header line:
<?php
function check_remote_file($url = "http://www.google.com/not-exist.gif")
{
// -- first, fetch the domain
$bits = parse_url($url);
$domain = $bits['host'];
// -- check to see if we are able to connect to the remote server
$fp = fsockopen($domain,80,$errno,$errstr);
if (!$fp)
{
die("Could not connect. [ ".$errno." ] : ".$errstr."\n");
} else {
echo "Connected to ".$domain."\n";
}
// -- construct a HTTP request for the file requested.
// -- if someone just entered the domian name, request
// -- the default index
if ($bits['path'] == '')
{
$path = '/';
} else {
$path = $bits['path'];
}
$req = "GET ".$path." HTTP/1.1\r\n";
$req .= "Host: ".$domain."\r\n";
$req .= "Connection: Close\r\n\r\n";
// -- send the request
fwrite($fp,$req);
// -- grab first few bytes of the response
$response = fgets($fp,1024);
// -- close the connection
fclose($fp);
echo 'Response : '.$response;
// -- check the response for the status code
// -- 4xx and 5xx are errors
// -- 200 is okay, good request, file exists
// -- 304 is Not modified
preg_match_all("|^(?:.*?)([0-9]{3})(?:.*?)$|m",$response,$results);
if ($results[1][0] == 200 || $results[1][0] == 304)
{
echo basename($path) == '' ? '/' : basename($path); echo " exists on ".$domain."\n";
} else {
echo basename($path) == '' ? '/' : basename($path); echo " does not exist on ".$domain."\n";
}
}
check_remote_file();
check_remote_file("http://www.google.com");
check_remote_file("http://www.google.com/images/logo_sm.gif");
?>
Here is a sample run so you can see what its doing :
fyrestrtr@phoenix ~/php $ php -q remote-image-check.php
Connected to www.google.com
Response : HTTP/1.1 404 Not Found
not-exist.gif does not exist on www.google.com
Connected to www.google.com
Response : HTTP/1.1 200 OK
/ exists on www.google.com
Connected to www.google.com
Response : HTTP/1.1 200 OK
logo_sm.gif exists on www.google.com
Things you can improve on :
You can modify the regular expression. Its a very "dirty" expression (imo). You can also add checks for various other HTTP status codes (or atleast their ranges). I put this together while writing this response, so hopefully there aren't any obvious bugs. Feel free to improve/comment/use in your own scripts.
latheesan 12-29-2005, 10:42 AM Wowww fyrestrtr,
once again, a superb suggestion. It looks a lil complicated for my level of uderstand of PHP, but i'll try to play around with it and see if i can get it to work.
Once again, thanks fyrestrtr
stdunbar 12-29-2005, 12:31 PM A quick comment - the code that fyrestrtr shows does exactly what you want but I might change the GET to a HEAD. The problem with the GET is that it tells the remote server to go ahead an send the entire content. A HEAD request tells the remote server to generate the HTTP headers but nothing else.
Depending on the size of the images involved this could improve the scalability of your application.
latheesan 12-29-2005, 02:07 PM hey stdunbar,
Im not sure which part you want me to change..
stdunbar 12-29-2005, 02:08 PM From:
$req = "GET ".$path." HTTP/1.1\r\n";
to
$req = "HEAD ".$path." HTTP/1.1\r\n";
latheesan 12-29-2005, 02:22 PM Ahhh... Ok, i changed it and tested it. All working.
Thanks everyone :D
latheesan 12-29-2005, 02:31 PM Once last question.
Is it possible to place the function bit at the top of the script and then, later on when im printing the details from the db, could i do something like this
check_remote_file($banner);
to do this, what do i have to modify?
latheesan 12-29-2005, 02:43 PM nm, i got it :D
|