Manipulating the local file system with browser-based JavaScript and Node

I am making a project that needs to allow users to interact with the file system from a browser. I have a lot of experience writing client-side JavaScript, and I have a lot of experience writing Node scripts for things like web scraping, data analysis, and file system work. But this project will let users change things in the browser, and then save that data locally (and, eventually, to a web server) – and I have no experience with this.

I've installed browserify and browserify-fs to use Node's fs module in the browser, and used the example from the browserify-fs README to create a directory, write a file to it, and then read that file:

var fs = require('browserify-fs');

fs.mkdir("/home", function(err){
    if (err) throw err;

    fs.writeFile("/home/hello-world.txt", "Hello world!", function(err) {
        if (err) throw err;

        fs.readFile("/home/hello-world.txt", "utf-8", function(err, data) {
            if (err) throw err;

            console.log(data);
        });
    });
});

This "works" in the sense that it logs "Hello world!" in the console. But as far as I can tell, it does not create a directory or save a file locally. I have some vague sense that it is saving these things temporarily in the browser, and that they are deleted when I navigate away. But I want to actually create a directory and save a file in it locally. Can I do that with JavaScript alone? Is there a good tutorial on how to "close the loop" between browser-based JavaScript and Node?

Update

I've accepted T.J. Crowder's response – ExpressJS does, indeed, make client-server communication in JavaScript relatively simple. What I'm doing now is, I'm saving the user's entries to a global JSON object. When the user clicks a "save" button, I update the value of a hidden <input> element in a <form> element with the stringified JSON. Then I submit the form, and Express's app.post() plus the module body-parser give me everything in req.body. Then I can perform normal Node file system operations.


Solution 1:

Naturally, browser-hosted JavaScript cannot access the file system of the user's machine (at present; someday, some kind of sandboxed access may happen — the last attempt failed, but that doesn't mean the next one has to — the next attempt is in Chromium browsers now).

So to do this, you'll need two pieces:

  1. A browser piece, which does the UI with the user.

  2. A Node piece, which runs on the user's machine (and thus can access the file system) and which the browser piece uses to do the actual file operations.

Probably the easiest way for the pieces to interact would be HTTP, which you can trivially support using ExpressJS.

So for instance, if the user wants to delete a file:

  1. User clicks something to say "delete this file"
  2. Browser JavaScript sends the command to the Node process over HTTP via ajax
  3. Node process does the deletion and reports success/failure
  4. Browser JavaScript displays the result

Solution 2:

You cannot do this purely in Javascript. Javascript running on browsers does not have enough permission yet (there have been proposals) due to security reasons.

https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API/Introduction#restrictions

Because the file system is sandboxed, a web app cannot access another app's files. You also cannot read or write files to an arbitrary folder (for example, My Pictures and My Documents) on the user's hard drive.