28

I need to write a software that uses HTML5 and canvas.

The whole software should be able to run locally, without the need of a server. So I'm only able to use Javascript, no php.

The difficult part: I have to dynamically fetch the content of text-files which are needed during operation.

For example: When the software starts, I need the "config.json". And after the user made some desicions, I need "story1.txt" or "story2.txt" and so on.

My Problem:

I can't use Ajax, because Chrome blocks it - local Files aren't allowed to fetch other files' content. I always get an error-Message.

What I've tried so far:

  • Load Files with Ajax & jQuery

    Chrome doesn't allow me to load the file

  • Load File into script-Tag

    Even if I declare the JSON-File as js-Code, I can't access the content of the loaded File

  • Load File into invisible Iframe, and read its content

    Loading works, and I can see the code. But when I try to access the IFrame's content, I get the Chrome Error-Message again:

    "Uncaught SecurityError: Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match."
    

Question:

Is there a way to load a Textfile dynamically, or am I forced to use a Webserver?

Shadow The Vaccinated Wizard
  • 62,584
  • 26
  • 129
  • 194
maja
  • 14,242
  • 14
  • 72
  • 106
  • this error from chrome sometimes happen because the request origin URL is different from the file source URL. Try to put them on same server or localhost – amrswalha Nov 11 '13 at 09:12
  • How are you loading the text file? what's your code? If you have used like `c:/cccc.txt` will give cross browser error.Check this answer http://stackoverflow.com/a/19866904/1671639 – Praveen Nov 11 '13 at 09:13
  • @amrswalha: I don't have a server, and I don't access them via localhost. I have the files on my D-Parition, and the url looks like this: "file:///D:/visNov/index.html" -- I want to avoid using a server – maja Nov 11 '13 at 09:15
  • Why can't you set up a lightweight server locally as part of your product? - this is by far the more robust option. I've been playing with [node http-server](https://github.com/nodeapps/http-server) (there are other alternatives, but I like it because it has no overheads and little to no setup needed) - otherwise you are going to have to load chrome with the [`--disable-web-security` flag](http://stackoverflow.com/a/3177718) - which isn't good if you are developing a commercial product. – Emissary Nov 11 '13 at 09:16
  • @maja as you see from the error this is the problem the chrome block the request. Go to run and type Chrome.exe --allow-file-access-from-files or try Chrome.exe --disable-web-security – amrswalha Nov 11 '13 at 09:18
  • I'm trying to make installtion as simple as possible - and what is simpler than just copying the html and js-Files on the Desktop? But if the user needs to set that flag, using a lightweight server might be a better alternative – maja Nov 11 '13 at 09:19
  • You can always write a shell script or executable that will start everything behind the scenes in one click. – Emissary Nov 11 '13 at 09:21
  • possible duplicate of [Using a local file as a data source in JavaScript](http://stackoverflow.com/questions/13428532/using-a-local-file-as-a-data-source-in-javascript) – Shadow The Vaccinated Wizard Nov 11 '13 at 09:22
  • 1
    Dead end - I fear you just can't do that, at least not cross browser. If you want 100% offline app use something else. – Shadow The Vaccinated Wizard Nov 11 '13 at 09:24

8 Answers8

11

If you insist on using Chrome, it have some command line flags to allow access to/from local originated files (--allow-file-access-from-files / --disable-web-security). Do note that you need to run entire browser from scratch with those flags - i.e. if there's already any other Chrome windows open flags WON'T have any effect and that effect persists across ALL windows until Chrome is closed, which is, obviously huge hole in security.

You can set up a lightweight local server if you pack your "application" with some kind of automated setup script. This is still not very good, because you'd need to install executable that user might not want or even be completely unable to install due to restrictions.

You can pack your HTML/JS-based app as Chrome extension - extensions have much wider permissions than random code, but then you'd need to either distribute it through Google Play or provide instructions to manually install extensions for your users.

And finally, you can format all the data, including your configuration and text files your mentioned as valid JavaScript code - i.e. pack a story1.txt to story1.js like:

var myapp.story1 = "Complete text of story1.txt"

and then just dynamically select stuff you need from corresponding vars or even use DOM manipulation to only load scripts you need through dynamically adding <script> tags. In my opinion that would be best option because it is less intrusive: it doesn't requires any installation/reconfiguration, it just works out-of-box.

Oleg V. Volkov
  • 19,811
  • 3
  • 40
  • 60
  • 1
    I don't want the user to use an installer / to install a webserver, or to install a plugin (it wouldn't even be cross-browser-compatible). But I also can't tell him to close his browser, and reopen it with this flag. So I just changed all Files to js-Files. It isn't as beautifull as pure Text or JSON-Files, but it works quite well. – maja Nov 17 '13 at 09:38
  • It's also possible to embed files within an HTML document using [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs). – Anderson Green Oct 30 '20 at 03:53
6

If you just need a quick and easy "legal" web server to trick your browser into thinking that it isn't pulling from the local file system, just use Python's simple HTPP server. It simply serves up files on request from whatever directory it was invoked from. The server is otherwise dumb. It will not execute PHP scripts or anything. Here's how:

  1. Install Python 2.7 on your development machine. This is the only thing that this fix will permanently install.
  2. Open up your command line / terminal window.
  3. Switch to the directory where your scripts reside.

cd /Users/codemonkey/myCoolNewApp (e.g. on a Mac)

  1. Run the following:

    python -m SimpleHTTPServer 80

On a Mac or Linux box, you may need to use sudo:

sudo python -m SimpleHTTPServer 80

  1. Open up your browser and type in:

http://localhost/myapp.html (substitute "myapp.html" with your script name)

  1. And the people rejoice.
  2. To stop the web server, go back to the terminal window in which it is running and hit Ctrl-C. Or shut the computer down. This server will need to be restarted using step 4 each time you want to run it.

You can get really fancy and run multiple instances on different ports, but that's beyond the scope of this quick fix.

Alex Matan
  • 69
  • 1
  • 1
4

You have to put your local files on the same server. If you are running on local server you have to install some webserver as Apache to get access to your "remote" location.

Every Modern browser stops this, because you mustn't read local files from ANY USER. Even if you are running from localhost.

  • Yes, it's a dead end. But putting all files in the same directory is only considerable, if you only have a handful of files. So it's no option for me - the whole code would be a mess. Nevertheless +1, because it would be the right answer in that case. – maja Nov 17 '13 at 09:43
4

I have found that firefox will run html and js locally.

yeahdixon
  • 6,131
  • 1
  • 36
  • 42
2

You can Load the Local file in Chrome Browser locally without Using AJAX. you can use normally use jQuery function like $.getJSON() for loading the file in chrome browser.

But if you use this jQuery functionality then chrome Web Security will Block your function to access file form files packages. On Firefox browser it perfectly runs but if your requirement is the chrome browser then you must need to set some Chromium Flags using Command Line.

Here is Some steps for you to set Chromium Flags which enables you some extra features which helps you access the data file from your local system. these are:-

  1. Exit or close any running-instance of chrome.
  2. Find the shortcut you normally use to launch chrome.
  3. Create a copy of it.
  4. Right click on the new shortcut, and select Properties.
  5. At the very end of the Target: text box, add a space and then the desired command line flags. It should something like: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security
  6. click "apply" button and then "ok".
  7. Double click the new shortcut to launch chrome with the new command line flags.

Note: Remember your Flags now set only for this chrome icon. so start your application with this chrome icon.

Yash Mangla
  • 133
  • 9
  • 1
    This is essentially the same answer as the accepted one from two years ago… just wrapped in a guide to managing a Windows desktop. – Quentin Aug 26 '15 at 08:43
  • yeah, this is earlier example but these steps helpful for End user to understand these functionality if he is handling window desktop. – Yash Mangla Aug 27 '15 at 08:04
2

Depending on your requirements, using fetch (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) is an option:

  fetch("./config.json").then(function(res) {
    // res instanceof Response == true.
    if (res.ok) {
      res.json().then(function(data) {            
        console.log(data);
      });
    } else {
      console.log("Looks like the response wasn't perfect, got status", res.status);
    }
  }, function(e) {
    console.log("Fetch failed!", e);
  });
Stucco
  • 323
  • 2
  • 18
  • It's possible that you're using a browser that isn't compatible. Which browser did you use? What version was it? Is it supposed to be supported (see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#Browser_compatibility)? – Stucco Jul 31 '17 at 21:14
  • @Stucco, `Fetch API cannot load file://***/config.json. URL scheme must be "http" or "https" for CORS request.` . Browser supports Fetch Api, but the call for file protocol is denied by CORS policy. – user1742529 Aug 13 '19 at 05:10
1

I would make a Chrome extension if your requirements allow that. They are easy to make and can work quite well for you. http://developer.chrome.com/extensions/index.html

1

What you are describing (and the proposed solution) seriously undermines the security of the browser.

should be able to run locally, without the need of a server

So how does the software get on the machine? Unless you intend sending DVDs in the post, deployment of the software can be as an HTML5 app using Manifest based caching (supported in all modern browsers, including Chrome, MSIE and Firefox). What this does not cater for is storing data as normal files - but you can keep data in local storage.

symcbean
  • 45,607
  • 5
  • 49
  • 83