210

I'm trying to create a website that can be downloaded and run locally by launching its index file.

All the files are local, no resources are used online.

When I try to use the AJAXSLT plugin for jQuery to process an XML file with an XSL template (in sub directories), I receive the following errors:

XMLHttpRequest cannot load file:///C:/path/to/XSL%20Website/data/home.xml. Origin null is not allowed by Access-Control-Allow-Origin.

XMLHttpRequest cannot load file:///C:/path/to/XSL%20Website/assets/xsl/main.xsl. Origin null is not allowed by Access-Control-Allow-Origin.

The index file making the request is file:///C:/path/to/XSL%20Website/index.html while the JavaScript files used are stored in file:///C:/path/to/XSL%20Website/assets/js/.

How can I do to fix this issue?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Kevin Herrera
  • 2,941
  • 3
  • 19
  • 13

10 Answers10

178

For instances where running a local webserver is not an option, you can allow Chrome access to file:// files via a browser switch. After some digging, I found this discussion, which mentions a browser switch in opening post. Run your Chrome instance with:

chrome.exe --allow-file-access-from-files

This may be acceptable for development environments, but little else. You certainly don't want this on all the time. This still appears to be an open issue (as of Jan 2011).

See also: Problems with jQuery getJSON using local files in Chrome

Community
  • 1
  • 1
Courtney Christensen
  • 9,165
  • 5
  • 47
  • 56
  • 1
    @Rich, glad it helped! I wonder if there will be greater demand for this with Google's push toward browser-based apps. I think demand will only grow. – Courtney Christensen Jan 31 '11 at 23:54
  • 4
    this was helpful for macs OS X http://cweagans.net/blog/2011/1/24/command-line-flags-google-chrome-mac-osx – kinet Feb 12 '11 at 06:43
  • 1
    Thanks, I was wondering where I coded wrong, seems browser is the issue. – Arda Jun 03 '11 at 10:54
  • 4
    Is there any reason --allow-file-access-from-files would not fix the issue. I am simply trying to load a script file like so $.getScript("application.js"); and get the error described in the question. – Denzo Jul 25 '12 at 04:17
  • 1
    This works, however "Before you execute the command, make sure all of your Chrome window is closed and not otherwise running. Or, the command line param would not be effective. "chrome.exe --allow-file-access-from-files"" (http://stackoverflow.com/a/4208455/1272428) – rluks Nov 19 '15 at 12:57
86

Essentially the only way to deal with this is to have a webserver running on localhost and to serve them from there.

It is insecure for a browser to allow an ajax request to access any file on your computer, therefore most browsers seem to treat "file://" requests as having no origin for the purpose of "Same Origin Policy"

Starting a webserver can be as trivial as cding into the directory the files are in and running:

python -m http.server

[Edit Thanks @alextercete, for pointing out that it has updated in Python3]

Singletoned
  • 5,089
  • 3
  • 30
  • 32
  • 1
    I'm hoping to develop a solution that does not require the user to use anything more than their web browser. Using Python, any interpreter, or any non system agnostic software is not viable. – Kevin Herrera Nov 28 '10 at 05:40
  • 5
    Well the only other solution I can think of is to load the entire thing in one single page so that you don't need to make any ajax requests to the file system. – Singletoned Nov 30 '10 at 13:34
  • 2
    Thank you @Singletoned ! I'm using your solution and it's very handy ! – Hendy Irawan Dec 01 '10 at 17:07
  • 4
    And if you are using Python 3, the command would be `python -m http.server`. – alextercete Sep 29 '12 at 20:53
5

This solution will allow you to load a local script using jQuery.getScript(). This is a global setting but you can also set the crossDomain option on a per-request basis.

$.ajaxPrefilter( "json script", function( options ) {
  options.crossDomain = true;
});
Renaud
  • 4,569
  • 7
  • 41
  • 72
5

What about using the javascript FileReader function to open the local file, ie:

<input type="file" name="filename" id="filename">
<script>
$("#filename").change(function (e) {
  if (e.target.files != undefined) {
    var reader = new FileReader();
    reader.onload = function (e) {
        // Get all the contents in the file
        var data = e.target.result; 
        // other stuffss................            
    };
    reader.readAsText(e.target.files.item(0));
  }
});
</script>

Now Click Choose file button and browse to the file file:///C:/path/to/XSL%20Website/data/home.xml

suhailvs
  • 20,182
  • 14
  • 100
  • 98
4

Here is an applescript that will launch Chrome with the --allow-file-access-from-files switch turned on, for OSX/Chrome devs out there:

set chromePath to POSIX path of "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"    
set switch to " --allow-file-access-from-files"
do shell script (quoted form of chromePath) & switch & " > /dev/null 2>&1 &"
ericsoco
  • 24,913
  • 29
  • 97
  • 127
  • 14
    You can just use [open(1)](http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/open.1.html) to add the flags: `open -a 'Google Chrome' --args --allow-file-access-from-files`. – Josh Lee Aug 10 '11 at 16:44
3

Launch chrome like so to bypass this restriction: open -a "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --args --allow-file-access-from-files.

Derived from Josh Lee's comment but I needed to specify the full path to Google Chrome so as to avoid having Google Chrome opening from my Windows partition (in Parallels).

Community
  • 1
  • 1
Stunner
  • 12,025
  • 12
  • 86
  • 145
2

The way I just worked around this is not to use XMLHTTPRequest at all, but include the data needed in a separate javascript file instead. (In my case I needed a binary SQLite blob to use with https://github.com/kripken/sql.js/)

I created a file called base64_data.js (and used btoa() to convert the data that I needed and insert it into a <div> so I could copy it).

var base64_data = "U1FMaXRlIGZvcm1hdCAzAAQA ...<snip lots of data> AhEHwA==";

and then included the data in the html like normal javascript:

<div id="test"></div>

<script src="base64_data.js"></script>
<script>
    data = atob(base64_data);
    var sqldb = new SQL.Database(data);
    // Database test code from the sql.js project
    var test = sqldb.exec("SELECT * FROM Genre");
    document.getElementById("test").textContent = JSON.stringify(test);
</script>

I imagine it would be trivial to modify this to read JSON, maybe even XML; I'll leave that as an exercise for the reader ;)

Anthony Briggs
  • 3,395
  • 1
  • 22
  • 12
1

You can try putting 'Access-Control-Allow-Origin':'*' in response.writeHead(, {[here]}).

nstCactus
  • 5,141
  • 2
  • 30
  • 41
Shikon
  • 11
  • 1
  • 6
    where does response.writeHead come from, how do I call it and where? Can you give more examples? Keep in mind this is a local file system not a server. My understanding is that value can only be set from a server? – Joseph Astrahan Jul 16 '14 at 02:09
0

use the 'web server for chrome app'. (you actually have it on your pc, wether you know or not. just search it in cortana!). open it and click 'choose file' choose the folder with your file in it. do not actually select your file. select your files folder then click on the link(s) under the 'choose folder' button.

if it doesnt take you to the file, then add the name of the file to the urs. like this:

   https://127.0.0.1:8887/fileName.txt

link to web server for chrome: click me

person the human
  • 345
  • 4
  • 15
0

If you only need to access the files locally then you can include the exact path to the file, rather than using

../images/img.jpg

use

C:/Users/username/directoryToImg/img.jpg

The reason CORS is happening is because you are trying to traverse to another directory within a webpage, by including the direct path you are not changing directory, you are pulling from a direct location.