I'm developing a JavaScript application that's meant to be run either from a web server (over http) or from the file system (on a file:// URL).
As part of this code, I need to use XMLHttpRequest to load files in the same directory as the page and in subdirectories of the page.
This code works fine ("PASS") when executed on a web server, but doesn't work ("FAIL") in Internet Explorer 8 when run off the file system:
<html><head>
<script>
window.onload = function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", window.location.href, false);
xhr.send(null);
if (/TestString/.test(xhr.responseText)) {
document.body.innerHTML="<p>PASS</p>";
}
}
</script>
<body><p>FAIL</p></body>
Of course, at first it fails because no scripts can run at all on the file system; the user is prompted a yellow bar, warning that "To help protect your security, Internet Explorer has restricted this webpage from running scripts or ActiveX controls that could access your computer."
But even once I click on the bar and "Allow Blocked Content" the page still fails; I get an "Access is Denied" error on the xhr.open call.
This puzzles me, because MSDN says that "For development purposes, the file:// protocol is allowed from the Local Machine zone." This local file should be part of the Local Machine Zone, right?
How can I get code like this to work? I'm fine with prompting the user with security warnings; I'm not OK with forcing them to turn off security in the control panel.
EDIT: I am not, in fact, loading an XML document in my case; I'm loading a plain text file (.txt).
The async parameter of the open() method should be set to true: xhttp.
To send an HTTP request, create an XMLHttpRequest object, open a URL, and send the request. After the transaction completes, the object will contain useful information such as the response body and the HTTP status of the result.
XMLHttpRequest (XHR) is a JavaScript API to create AJAX requests. Its methods provide the ability to send network requests between the browser and a server.
XMLHttpRequest is used heavily in AJAX programming. Despite its name, XMLHttpRequest can be used to retrieve any type of data, not just XML. If your communication needs to involve receiving event data or message data from a server, consider using server-sent events through the EventSource interface.
How can I get code like this to work?
As suggested above, this looks like a fault in Microsoft XMLHttpRequest
. jQuery (Jul 2011) also writes:-
Microsoft failed to properly implement the XMLHttpRequest in IE7 (can't request local files)
I confirm this failure for IE8 too.
A solution is to use new window.ActiveXObject( "Microsoft.XMLHTTP" )
for local files if XMLHttpRequest
doesn't work.
The failure is in the xhr.open
line so it can be caught there and then try ActiveXObject
as follows:-
var xhr = new XMLHttpRequest()
try {
xhr.open('GET', url, true)
}
catch(e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP')
xhr.open('GET', url, true)
}
catch (e1) {
throw new Error("Exception during GET request: " + e1)
}
}
This code will at least use standard XMLHttpRequest
for IE9 (untested) and future IE browsers if/when Microsoft fixes the fault. With the jQuery
code above, non standard Microsoft.XMLHTTP
will be used whenever ActiveXObject
is available, even if Microsoft fix the fault.
I know this is old - but wanted to clarify what is going on with a little more detail, and offer a couple of potential options.
First off this is actually not a flaw within IE, but a security feature that exists in Chrome as well.
Basically, any resource URI with file:// prefix is not allowed to load any other resource URI with file:// prefix using XMLHttpRequest.
In IE you will see an Access Denied message. In Chrome you will see "Failed to load resource: Origin null is not allowed by Access-Control-Allow-Origin" More info -> Information on IE and Information on Chrome (look for --allow-file-access-from-files)
An interesting thing with IE is that if you are using the .NET Browser Control inside of a WinForm or Silverlight App, this feature is disabled, and you will not have the same issues.
There are a couple of workarounds that I am aware of - none of which are ideal, as they disable a measure of security protection
Once again, this is a security feature within browsers to mitigate potential threat vectors - similar to the Cross Domain scripting blocks.
Hmm, could it be the difference between the native XMLHttpRequest object and the ActiveX one? I seem to remember something about that. That is, instead of
var xhr = new XMLHttpRequest();
try
var xhr = new ActiveXObject("MSXML2.XMLHTTP");
Obviously, put some checks in place to see if the browser supports ActiveX. Of course, this is limited to IE only, as well.
I just happened to stumble across exactly the same problem. As suggested above, the non-native ActiveX "constructor" works. I’m not really sure whether there are different policies applied to the two objects, but since jQuery mentions the same problem as well, it may be a genuine bug. Here is the relevant piece of code from the jQuery source (1.4.2, line 4948):
// Create the request object; Microsoft failed to properly
// implement the XMLHttpRequest in IE7 (can't request local files),
// so we use the ActiveXObject when it is available
// This function can be overriden by calling jQuery.ajaxSetup
xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
function() {
return new window.XMLHttpRequest();
} :
function() {
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With