## Filesystem API Author #### Sergey Sinyakin [Behemoth86](https://github.com/Behemoth86)

Preface

The FileSystem API and File API, a web application can create, read, view and write files and/or directories in a virtual, sandboxed file system.

The API description is divided into the following sections:
  • Reading and managing files: File / Blob, FileList, FileReader
  • Create & Burn: BlobBuilder, FileWriter
  • Work with directories and access rights:
    DirectoryReader, FileEntry / DirectoryEntry, LocalFileSystem
#### Benefits of using api file systems The file and directory API is an important programming interface for the following reasons: - Applications can use offline functions, as well as storage functions that allow large binary data sets to be processed. - Applications have the ability to preload and cache resources, which improves performance. - The application user has the ability to directly edit the files located on his computer. - Users are provided with a file storage interface that is similar to a file system.
### Examples of applications using the API files and directories: - Applications with continuous loading. - Video games or other applications with a lot of media resources. - Audio or photo editor with the ability to work offline or a local cache. - Offline video player. - Offline email client.

Browser support

In this table first row is browser, the second is version

Chrome Edge Firefox IE Opera Safari
13 ≤18 50 No 15 11.1

*Today only Chrome has a full support of FileSystem API

### FileSystem API Objects: - File - allows you to get such read-only information as name, size, mimetype and more. - FileList - "array" of File objects. - Blob - an entity that allows you to parse a file by bytes.
Filesystem API includes the following interfaces:
  • Asynchronous API

    The asynchronous API should be used for most operations, to prevent file system accesses from blocking the entire browser if used on the main thread. It includes the following interfaces:

  • Synchronous API

    The synchronous API is should only be used in Workers; these calls block until they're finished executing, and simply return the results instead of using callbacks. Using them on the main thread will block the browser, which is naughty. The interfaces below otherwise mirror the ones from the asynchronous API.

  • LocalFileSystem

    Gives you access to a sandboxed file system.

  • LocalFileSystemSync

    You can request access to a sandboxed file system by requesting LocalFileSystemSync object from within a web worker.

  • LockedFile

    Provides tools to deal with a given file with all the necessary locks.

  • Metadata

    The Metadata interface is used by the File and Directory Entries API to contain information about a file system entry. This metadata includes the file's size and modification date and time.

In this presentation we will look at the asynchronous version of the API

Let's GO!

1 Step

Get access to the HTML5 file system by making a request to the LocalFile system object using the global window.requestFileSystem () method:


            window.requestFileSystem(type, size, successCallback, opt_errorCallback);
          

Example:


            window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
            window.requestFileSystem(window.TEMPORARY, 5*1024*1024, initFS, errorHandler);
            function initFS(fs){
                                alert("Welcome to Filesystem! It's showtime"); // Just to check if everything is OK 
            }
            function errorHandler(){
                                    console.log('An error occured');
            }
          
type

Persistent storage - is storage that stays in the browser unless the user expunges it or the app deletes it.

Temporary storage - Transient storage is available to any web app. It is automatic and does not need to be requested, but the browser can delete the storage without warning.

size

The size (in bytes) of storage that the application will need.

successCallback

Callback function executed in case of successful access to the file system. Its argument is an object of type FileSystem.

opt_errorCallback

Optional callback function for handling errors. It is also called when file system access errors occur. The parameter is an object of type FileError.

2 Step(Work with directory)

The first thing to create in the file system is memory chunks, or directories. Although the root folder already exists, you do not need to put all the files there. Directories are created by a DirectoryEntry. In the following example, we create a directory called Documents inside the root folder:


            fs.root.getDirectory('Documents', {create: true}, function(dirEntry) {
              alert('You have just created the ' + dirEntry.name + ' directory.');
            }, errorHandler);
          

The getDirectory () method is used both for reading and creating a directory. As the first parameter, you can pass the name or route as a directory for searching or creating. If you need to create a directory, then the second parameter is true.

Now it's time to see what is in our file system. Create a DirectoryReader object and use the readEntries () method to read the contents of a directory.


            fs.root.getDirectory('Documents', {}, function(dirEntry){
              var dirReader = dirEntry.createReader();
              dirReader.readEntries(function(entries) {
             for(var i = 0; i <= entries.length; i++) {
             var entry = entries[i];
             if (entry.isDirectory){
             console.log('Directory: ' + entry.fullPath);
             }
             else if (entry.isFile){
             console.log('File: ' + entry.fullPath);
             }
             }
             
              }, errorHandler);
            }, errorHandler);
          

The isDirectory and isFile properties are used to respectively obtain different output of directories and files. In addition, we use the fullPath property to get the full entry route instead of just one name.

There are two ways to remove DirectoryEntry from the file system: remove () and removeRecursively (). The first one deletes this folder only if it is empty. Otherwise, you will get an error.


            fs.root.getDirectory('Documents/Music', {}, function(dirEntry) {
              dirEntry.remove(function(){
             console.log('Directory successfully removed.');
              }, errorHandler);
            }, errorHandler);
          

If there are files inside the Music folder, then you will need to apply the second method, which recursively deletes the folder and all its contents.


            fs.root.getDirectory('Documents/Music', {}, function(dirEntry) {
              dirEntry.removeRecursively(function(){
             console.log('Directory successufully removed.');
              }, errorHandler);
            }, errorHandler);
          

3 Step(Work with Files)

The following example creates an empty test.txt in the root folder:


            fs.root.getFile('test.txt', {create: true, exclusive: true}, function(fileEntry) {
              alert('A file ' + fileEntry.name + ' was created successfully.');
            }, errorHandler);
          

We extract the test.txt file and create a FileWriter object for it. Then we attach the contents to it, creating a new BlobBuilder object and applying the write () method to FileWriter.


            fs.root.getFile('test.txt', {}, function(fileEntry) {
              fileEntry.file(function(file) {
             var reader = new FileReader();
             reader.onloadend = function(e) {
             alert(this.result);
             };
             reader.readAsText(file);
              }, errorHandler);
            }, errorHandler);
          

You can rearrange the application to write to the end of the file using the seek () method. seek takes an offset in bytes as an argument and sets the location of the application to write to files for this offset.


            fs.root.getFile('test.txt', {create: false}, function(fileEntry) {
              fileEntry.createWriter(function(fileWriter) {
             fileWriter.seek(fileWriter.length);
             window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder;
             var bb = new BlobBuilder();
             bb.append('Yes, it is!');
             fileWriter.write(bb.getBlob('text/plain'));
              }, errorHandler);
            }, errorHandler);
          

To remove a file from the system, simply call entry.remove (). The first argument to this method is a callback function with a null parameter, which is called when the file is successfully deleted. The second is a random error callback.


            fs.root.getFile('test.txt', {create: false}, function(fileEntry) {
              fileEntry.remove(function() {
             console.log('File successufully removed.');
              }, errorHandler);
            }, errorHandler);
          

4 Step(File and Folder Management)

FileEntry and DirectoryEntry share the same methods of copying the API, moving and renaming inputs. Two methods can be used for these operations: copyTo () and moveTo (). They both take the same parameters:


            copyTo(parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback);
            moveTo(parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback);
          

The first parameter is the parent folder for moving / copying input to it. The second is an arbitrary new name given to the moved / copied input, which is actually required when you copy the input in the same folder, otherwise you will have an error. The third and fourth parameters were explained earlier.

Let's see some examples. Copy the test.txt file from root to the Documents directory.


              function copy(currDir, srcEntry, destDir) {
                currDir.getFile(srcEntry, {}, function(fileEntry) {
              currDir.getDirectory(destDir, {}, function(dirEntry) {
              fileEntry.copyTo(dirEntry);
              }, errorHandler);
                }, errorHandler);
              }
              
              copy(fs.root, 'test.txt', 'Documents/');
            

Moving .txt to Documents:


              function move(currDir, srcEntry, dirName) {
                currDir.getFile(srcEntry, {}, function(fileEntry) {
              currDir.getDirectory(dirName, {}, function(dirEntry) {
              fileEntry.moveTo(dirEntry);
              }, errorHandler);
                }, errorHandler);
              }
              move(fs.root, 'test.txt', 'Documents/');
            

Rename test.txt into text.txt


              function rename(currDir, srcEntry, newName) {
                currDir.getFile(srcEntry, {}, function(fileEntry) {
              fileEntry.moveTo(currDir, newName);
                }, errorHandler);
              }
              
              rename(fs.root, 'test.txt', 'text.txt');
            
For a deeper study of FileSystem API you can use the following links on W3C: - [File API: Directories and System](http://www.w3.org/TR/file-system-api/) - [File API: Writer](http://www.w3.org/TR/file-writer-api/) - [File API](http://www.w3.org/TR/file-upload/)

Epilogue

The file system API is a powerful and easy-to-use technology that provides web developers with a host of new features when building web applications. This technology is still fairly new and not widely supported by major browsers.

Thanks for watching!