[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

javascript getHTTPObject file URL check problem

Posted on 2012-09-04
9
Medium Priority
?
1,220 Views
Last Modified: 2012-09-06
I am attempting to use javascript to check the existence of a file URL. From a related thread, it was suggested (by fourck) I look at this tutorial:

http://x10hosting.com/forums/tutorials/76824-checking-if-file-url-exists-using-javascript-ajax.html

I did, and it works pretty well. However, the tutorial was taking "file exists/does not exists" actions down inside one of the functions (see function "handleHttpResponse_check()" in code below). I would prefer it set a flag indicating whether the file was found, since I want to make multiple calls to the "check_file(fn)" function. That is, I would like to take action in my IF/ELSE block, near the top of the example (see below).

So, in the "handleHttpResponse_check()" I instead set a variable "file_found" equal to either true or false, and the "check_file()" function returns that boolean value.

However, my "IF" statement never sees a return value of "true"... even if the file exists. To test, I put Alert statements in both "handleHttpResponse_check()" and my "IF/ELSE" block, and I will get contradictory Alerts... the one from "handleHttpResponse_check()" will say file was found, but the "IF/ELSE" block says the opposite.

Any idea what's going on? I have included my entire code below... just copy/paste it into a "anyname.html" file and open with your browser... thanks.

<script language="JavaScript">

http_check = getHTTPObject();

var file_found;

//------------ If/else based on whether image found -----------
if(check_file('http://www.jon-schmid.com/yamaha.jpg')){
	alert("Found my image");
}else{
	alert("Did not find my image");
}

//-------------------------------------------------------------
function check_file(path_of_file) 
{
    http_check.open("HEAD", path_of_file);
    http_check.onreadystatechange = handleHttpResponse_check;
    http_check.send(null);
    return file_found;
}

//-------------------------------------------------------------
function handleHttpResponse_check()
{
    if(http_check.readyState == 4){
        if (http_check.status == 200) {
            //---original example took "true" action here
            alert("check_file is TRUE"); 
            file_found = true;
        }else {
            //---original example took "false" action here
            alert("check_file is FALSE");
            file_found = false;
        }
    }
}

//-------------------------------------------------------------
function getHTTPObject(){ 
  //Create a boolean variable to check for a valid Internet Explorer instance.
var xmlhttp = false;
//Check if we are using IE.
 try {
  //If the Javascript version is greater than 5.
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  //If not, then use the older active x object.
  try {
  //If we are using Internet Explorer.
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
 } catch (E) {
//Else we must be using a non-IE browser.
xmlhttp = false;
 }
}
//If we are using a non-IE browser, create a javascript instance of the object.
 if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
 xmlhttp = new XMLHttpRequest();
 }
 
  return xmlhttp;
}

</script>

Open in new window

0
Comment
Question by:futuremoose
  • 3
  • 3
  • 2
  • +1
9 Comments
 
LVL 16

Expert Comment

by:grahamnonweiler
ID: 38366677
You have set "file_found" as a local variable while you are trying to use it as a global.

Change line 5:

    file_found=false;

Change line 34 (and add extra line):

   if(file_found) { return true; }
   return false;
0
 

Author Comment

by:futuremoose
ID: 38366731
grahamnonweiler, thanks for your reply.

Concerning line 5: The "file_found" variable is declared outside of any function... doesn't that make it global accessible? I went ahead and changed it as you suggested anyhow.

Concerning line 34: I don't want "handleHttpResponse_check()" to return a true or false value (as you can see in the code, it is already being called to set the value of "http_check.onreadystatechange"). I wanted to set the "file_found" boolean variable.

I did change the "check_file" function to use
        if(file_found) {return true;}
        return false;

instead of just "return file_found", though I'm not sure that make a difference.

Still doesn't work. But one thing I did notice... the alert from inside the "IF/ELSE" block always seems to come up before the alert from inside the "handleHttpResponse_check()"... not sure what that means, if anything
0
 
LVL 5

Expert Comment

by:dnzone88
ID: 38366859
You are using Ajax and Ajax is asynchronous process. That is why the alert from inside the "IF/ESLE" block execute before the alert from inside the "handleHttpResponse_check()".

If you really need synchronous Ajax call, you can use jQuery's jQuery.ajax() api. it support synchronous ajax.

Hope this information helps.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 16

Expert Comment

by:grahamnonweiler
ID: 38367286
As @dnzone88 points out, AJAX is an asynchronous process, and when called by Javascript control immediately returns to the next action of the calling script.

Normally, when using AJAX you would change the value of another element, or call another function after the AJAX has completed.

An example:

<html>
<head>
<script language="JavaScript">

function doCheckFile(url) {

  var xmlHttp;
  try  { xmlHttp=new XMLHttpRequest(); }
  catch (e) {
    try { xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); }
    catch (e) { 
	try { xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");  }
      catch (e) {
        return false;
      }
    }
  }
  xmlHttp.onreadystatechange=function() {
      if(xmlHttp.readyState==4) {
        if(xmlHttp.status==200) {
		document.getElementById('exampleEE').innerHTML='I found the file'+url;
	  } else {
		document.getElementById('exampleEE').innerHTML='I did <b>NOT</b> find the file'+url;
	  } 
      }
  }
  xmlHttp.open("HEAD",url,true);
  xmlHttp.send(null);
}

</script> 
</head>
<body>
<table><tr><td>This example will look for a file when you click the button, and display the results below the button</td></tr></table>
<table><tr><td><input type="button" value="Try My AJAX" onClick="doCheckFile('./index.php')"><br><br></td></tr></table>
<table><tr><td id="exampleEE" style="border:1px #777777 solid;padding:5px;"></td></tr></table>
</body>
</html>

Open in new window

0
 
LVL 82

Expert Comment

by:hielo
ID: 38367763
You need to make a synchronous call by explicitly setting the third parameter to open() false.  On your original post, change:
 http_check.open("HEAD", path_of_file);

to:
 http_check.open("HEAD", path_of_file, false);

and it will work as you desire.  Note however, that if you are making a lot of consecutive calls (or if the server is taking a long time to respond or even if you are on a slow connection), the browser will appear to be "frozen" while the ajax request(s) are still in progress.  The preferred approach is typically to do an asynchronous call (which means typically the third argument is set to true - as a matter of fact, if you omit the third parameter completely internally it is assumed you meant to set it to true and an asynchronous request is made).
0
 

Author Comment

by:futuremoose
ID: 38371269
grahamnonweiler, I tried your example (I changed the file location to "http://www.jon-schmid.com/yamaha.jpg") and it eventually worked in IE9 (the first couple of attempts it threw an error at line 27 ("Access Denied")... but after a couple of tries it started working OK. I can change the name of the file to something non-existent (...jpgx) and it will correctly report that it can not find the file.

hielo, I made the change you suggest, and it fixed the problem (at least in IE9) but introduced another... at line 19 in my original example (see above) if the file being sought does exist, everything's fine... but if it doesn't, I get an error (Access Denied, again) and it never returns to the IF/Else block.

Also, I've noticed none of this approach works in Chrome at all... sigh... apparently only jQuery stuff is guaranteed(?) to work across browser platforms.

hielo, if you can suggest a way to avoid the "Access Denied" error, that would help... I tried putting an IF (FILE_FOUND) {HTTP_CHECK.SEND(NULL)} at that line, but it didn't like that either.
0
 
LVL 16

Accepted Solution

by:
grahamnonweiler earned 750 total points
ID: 38371492
If you have access to server side scripting (PHP for example), you could write a very simple script that checks for the file and returns a result to the AJAX call.

Using ether async or sync AJAX this will produce a much more robust solution to your requirement.

The access denied error is being caused by you attempting to call "cross domain", and is basically a security feature of most modern browsers. Chrome will definately not like cross domain activity, and from a general "industry standard" behaviour you should only be checking for files within your own domain.
0
 
LVL 82

Assisted Solution

by:hielo
hielo earned 750 total points
ID: 38373659
When you do a synchronous request, once the request completes, THEN you check the status of the request.  In other words, there should not be any "onreadystatechange" statement.  Immediately after you execute send(), you then check the status of the returned status.

Looking at my previous post, I noticed that I did not make this point clear.  Here's what your code should look like:
//-------------------------------------------------------------
function check_file(path_of_file) 
{
    http_check.open("HEAD", path_of_file, false);
    http_check.send(null);
    return handleHttpResponse_check();
}

//-------------------------------------------------------------
function handleHttpResponse_check()
{
	var file_found=false;
    if(http_check.readyState == 4){
        if (http_check.status == 200) {
            //---original example took "true" action here
            alert("check_file is TRUE"); 
            file_found = true;
        }else {
            //---original example took "false" action here
            alert("check_file is FALSE");
        }
    }
return file_found;
}

Open in new window


NOTE: I updated both of your original functions so make sure you copy and paste what I just posted and try it.

Lastly, if in fact you are trying to access content from external sites, then it doesn't matter if you use synchronous or asynchronous requests.  By default, the browser will deny said requests.  The only workaround would be to have the remote server send a special header that essentially tells the browser "I know this request is not from my domain, but I don't care. Give him/her access to my content anyway!".  

Refer to:
http://enable-cors.org/
http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/


Note, in order for this to work the admin of the remote server has to explicitly send this header.  If the file you are trying to retrieve is from your own server, then this is not necessary.  Also, I believe this works in most modern browser only.  So if you are dealing with old browsers, you're out of luck.
0
 

Author Comment

by:futuremoose
ID: 38375166
Hi guys...

OK. Thanks for the updates. I am going to try what you have both suggested (thanks for the code, hielo) and close this thread (accept multiple solutions)

As it happens, I do have control over the servers in question, so I will implement some server side script and deal with it that way.

Thanks.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article discusses the difference between strict equality operator and equality operator in JavaScript. The Need: Because JavaScript performs an implicit type conversion when performing comparisons, we have to take this into account when wri…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…
Suggested Courses

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question