Dec 19 2013

HTML5: FileSystem API – Create Files and Store Them Locally Using JavaScript and Webkit

Advertisement

The FileSystem-API allows the creation of files and folders as well as their local storage using JavaScript. Files can be simple text files, but even more complex files such as images are possible. Modern Webkit browsers with HTML5 support are already able to handle the FileSystem-API. We show you how you can benefit from the new possibilities.

html5_filesystem

Access Local Filesystems

To be able to save files and folders from inside the web browser to the local hard drive you’ll need access to the filesystem. As this means a potential enormous security breach, it is not permitted by default. As a compromise between all or nothing, the FileSystem-API is only allowed to access a specific protected area on your local drive controlled by the browser. It is only this area, you will be allowed to read from and write to. It is not possible to access the whole of the local drive. Still you should be careful in implementing the technology thoroughly as trust will not be widespread, and for good reasons so. N’est ce pas, Monsieur Snowden?

The FileSystem-API can make use of local storage in two flavors. Storing can either be done temporarily, per session e.g. or files and folders can be stored permanently. Permanent storage does require the explicit permission by the user. This permission is requested by opening a tooltip below the URL bar, asking for confirmation.

Generally, to begin storing files, access to the filesystem needs to be established:

window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, SaveDatFileBro);
window.webkitRequestFileSystem(window.PERSISTENT , 1024*1024, SaveDatFileBro);

Using webkitRequestFileSystem() we choose whether we want to establish temporary (window.TEMPORARY) or permanent (window.PERSISTENT) storage as well as the required amount of space to be allocated. Our example above allocates 1 MB of space. Furthermore we define the function which will later be responsible for the actual access. Chrome allows the use of a maximum of 50% of the available disk space to store files temporarily, with each website limited to using 20% of that space.

As a fallback we could additionally attach a fourth parameter to webkitRequestFileSystem(). This would come into effect in case the allocation of storage space fails. While temporary files will be dynamically deleted when necessary, e.G. because the allocated storage has been used up, this is not true for permanently stored elements. These will stay stored until either the website or the user deletes them explicitly. As permanent storage request explicit permission through the opening of a tooltip below the address bar, it is mandatory to call webkitRequestFileSystem() separately:

navigator.webkitPersistentStorage.requestQuota(1024*1024, function() {
  window.webkitRequestFileSystem(window.PERSISTENT , 1024*1024, SaveDatFileBro);
})

The above example starts with asking the user for permission to store permanently using webkitPersistentStorage.requestQuota(). Only after this has been done can we use webkitRequestFileSystem() to allocate storage space.

filesystem_genehmigung

Permission Request in Chrome

The FileSystem-API follows the Same Origin Policy. This means, accessing files is only possible from the same website that created these files. This way you can be sure that no third parties will be able to scrape your files from somewhere.

The FileSystem-API is dependent on vendor prefixing to function correctly. At the time being, it will only work with Chrome.

Creating Files and Filling Them With Content

Our function SaveDatFileBro() is now permitted access to the allocated storage and able to create files and folders and put content to them. Using the method getFile() we access files or create them as needed:

function SaveDatFileBro(localstorage) {
  localstorage.root.getFile("info.txt", {create: true});
}

Our function SaveDatFileBro()“ needs to be equipped with a parameter to define access to the filesystem. I named this parameter localstorage. Via localstorage.root.getFile() we access the root of the filesystem and within that the file info.txt. In addition to defining the file name we attach a so-called object literal via getFile(). This literal contains one or more values telling its method what to do. The value create: true tells the method to create the file. create: false opens the file, in case it exists. createWriter() writes the contents of a BLOB to the file. A BLOB is a binary large object which is able to consist of random content such as text, images or other.

function SaveDatFileBro(localstorage) {
  localstorage.root.getFile("info.txt", {create: true}, function(DatFile) {
    DatFile.createWriter(function(DatContent) {
      var blob = new Blob(["Lorem Ipsum"], {type: "text/plain"});
      DatContent.write(blob);
    });
  });
}

To actually write contents to a file, the method getFile() receives a third parameter as a function call. This function carries the parameter DatFile. From here we call the method createWriter, which is responsible for filling the file with content. Another function, called via createWriter(), creates a BLOB, in our example a simple text BLOB. The object literal adds the type of content, in our case text/plain. Now we write() the BLOB to the file. To remove a file from the filesystem we would correspondingly use remove().

function SaveDatFileBro(localstorage) {
  localstorage.root.getFile("info.txt", {create: false}, function(DatFile) { DatFile.remove(function() {}); })
}

Although deleting does not require any additional information, the method stills expects a function. It can be left empty, though.

Creating Folders

Corresponding to getFile() for files, we will use getDirectory() for folders. The concept is the same. We are able to create folders and delete them again:

function SaveDatFileBro(localstorage) {
  localstorage.root.getDirectory("demo", {create: true}, function() {});
}

Our example creates the folder named demo. Afterwards you could create a file in that given folder like so:

function SaveDatFileBro(localstorage) {
  localstorage.root.getFile("/demo/info.txt", {create: true});
};

Remember to always create folders first, before you try to write content to them.

Using the method moveTo() allows you to move files from one folder to another. First you’ll need to call the method getFile() to define which file you’re about to move. Then the method getDirectory() defines the target directory and activates moveTo():

function SaveDatFileBro(localstorage) {
  localstorage.root.getFile("info.txt", {}, function(DatFile) {
    localstorage.root.getDirectory("demo/", {}, function(DatFolder) {
      datei.moveTo(DatFolder);
    });
  });
}

Besides moving files back and forth, moveTo() is only there to rename files. To achieve this, call the method separately, i.e. without getDirectory().

function SaveDatFileBro(localstorage) {
  localstorage.root.getFile("info.txt", {}, function(DatFile) {
    datei.moveTo(localstorage.root, "new.txt");
  });
}

Accessing Files from the Browser

As the created files and folders are stored to a protected area controlled by the browser, it is not possible to open them as usual by simple adding the file or folder names to the URL string. Instead we have a separate protocol to read-access these elements. Using the specific string you can embed them to other documents or simply call them from the address bar:

filesystem:http://www.example.com/persistent/info.txt
filesystem:http://www.example.com/temporary/info.txt

A URL for locally stored files always starts with filesystem: followed by the domain with leading http. As temporary files are separated from permanent files, the URL string contains persistent for permanently stored and temporary for temporarily stored files. Created folders and files follow from there.

FileSystem Viewed in Chrome’s DevTools

You are surely aware of Chrome’s DevTools being super useful for development purposes. Check cookies or other information easily. Now you can also check files and folders saved using the FileSystem-API. This needs to be manually enabled first. Go to chrome://flags/ , activate Enable Developer Tools experiments and restart Chrome. Afterwards go to the options, where you’ll find the new section Experiments.

N9iQnEm

From here you can enable FileSystem inspection. Now you’ll find FileSystem as part of the tab Resources, where you are able to see all files and folders created using the API.

filesystem_devtools
Checking the FileSystem in Chrome DevTools

Keep in mind, that DevTools only shows folders and files created. It is not possible to edit them from here.

Use Cases

The FileSystem-API enables the creation of web apps that are able to compete with local installations. Think of web-based email clients of word processors in the cloud, any use case basically, where files need to be stored or at least cached.

(dpe)

About the Author

Denis works as a freelance web designer since 2005.

Homepage

Comments and Discussions
  • sovr, 19 December 2013

    Whats the point? We can store files\json-data in localStorage (localStorage.setItem(file_name, serialized-content) and it supported not only in chrome. Also Blob-api unstable, this causes problems in various browsers, so many people still use flash-uploaders

  • jennifererrasta, 23 December 2013

    Wow that’s a wonderful comprehensive post. thank you for the effective and helpful information.

  • christinajosephone, 30 December 2013

    Good article for reference. Might be useful for all. keep it up

  • Smith, 06 January 2014

    Lovely information. great job and good luck.

  • ami, 08 May 2014

    Thanks,
    it is very good article but
    since i am new to javascript one full real example with write to local file and than read it will help me to really start use it.

  • CrisG, 12 May 2014

    Thank you very much. I think that, despite the “for security reasons” initial specs, web applications are getting too powerful and too useful to not letting a user save in their system what they have processed if they wish to. And yes “creation of web apps that are able to compete with local installations” is key. I am currently developing a weapp that shows a grid with a high amount of registers the user can order and filter as the wish really fast thanks to slickgrid (which is simply amazing): but they can not save in an excel file their results: they have waited for minutes to get 160.000 registers from the server, they have ordered and filtered 110.000 registers they are interested in in a matter of 2 seconds, and they have to upload them to server and download them again just to be able to save their work? Nagh! :)

  • Steve Wolf, 05 June 2014

    I’d like to add a small clarification. After enabling the “Developer Tools experiments” in the chrome://flags page and restarting Chrome – you can find the settings for enabling each experiment in the Developer Tools/Settings (the gear icon in the upper-right corner) and then click on Experiments under the “Settings” header.

    The article stated to “Afterwards go to the options, where you’ll find the new section Experiments.”

  • Steve Wolf, 05 June 2014

    Just completed my file write test given your instructions above. Brilliant. I’m creating an audio recording tool and I wanted to log the raw audio data to disk for debugging. Thanks again for the excellent post.

    BTW I thought some your readers might want a compressed example of creating and writing to a persistent file, so here is my code example:

    window.onload = function init() {
    var
    bb = new Blob(['Hello World!'], {type:’text/plain’})
    ;
    navigator.webkitPersistentStorage.requestQuota(1024*1024, function(grantedBytes) {
    window.webkitRequestFileSystem(window.PERSISTENT, 1024 * 1024, function(fs) {
    fs.root.getFile(‘log.txt’, {create: true}, function(fileEntry) { // fs.root is a DirectoryEntry object.
    fileEntry.createWriter(function(writer) { // writer is a FileWriter object.
    writer.write(bb);
    });
    });
    });
    });
    };

Leave a Reply

Comments are moderated - and rel="nofollow" is in use. Please no link dropping, no keywords or domains as names; do not spam, and do not advertise!

comments form
search form
 
image description image description