FileSystem API: Large File Client-Side Storage For Your Website
Tags: filesystem, javascript, webdev, html
Published: 2021-05-31 12:47:52

![Credits: SyncFusion JS File Manager](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3zv69qbk0tez8as3zj9.png)
My client asked me to provide **'download'** option on their video, just like native apps, where the video can be saved but would only be accessible to the specific app.

I finally stumbled upon FileSystem API, which allows sandboxed storage where the website will be given a specific storage space (just like how a virtual disk works).



I started testing my luck with a small video file. Two links that helped me the most were [HTML5 Rocks](https://www.html5rocks.com/en/tutorials/file/filesystem//) and [StackOverflow](https://stackoverflow.com/questions/11943499/playing-videos-from-chrome-filesystem-not-working-on-android)

I created the following function that requests FileSystem API from the browser:

```
initFileSystem() {
  //Possible ways to access filesystem
  window.requestFileSystem =
    window.requestFileSystem || window.webkitRequestFileSystem;

  //Define maximum size to allocate (I set it to 500MB), Set callback and an error handler
  window.requestFileSystem(
    window.TEMPORARY,
    500 * 1024 * 1024,
    onInitFs,
    errorHandler
  );

  function errorHandler(e) {
    console.log("Error: " + e);
  }
```

Then I created the following callback function that creates a video (getfile). I fetched the video using XHR and saved it as a blob using FileWriter.

```
//Callback function
function onInitFs(fs) {
  _fs = fs;
  saveVideo(fs);
}

function saveVideo(fs) {
  //Creates file named video.mp4
  fs.root.getFile(
    "video.mp4",
    { create: true, exclusive: true },
    //Writes file after fetching
    function (fileEntry) {
      fileEntry.createWriter(function (fileWriter) {
        fetchResource(fileWriter);
      }, errorHandler);
    },
    errorHandler
  );
}

//Fetches video using XHR
function fetchResource(fileWriter) {
  var xhr = new XMLHttpRequest();
  xhr.responseType = "arraybuffer";
  xhr.open("GET", "http://example:com/video.mp4", true);

  //Convert Video To Blob
  xhr.onload = function (e) {
    if (this.status == 200) {
      var bb = new Blob([this.response]);
      fileWriter.write(bb);
    } else {
      console.log(this.status);
    }
  };
  xhr.send();
}

```

Finally, I created an HTML5 video player and appended the video blob as URL.

```
<video id="ourVideo" controls=""></video>
```
> Note: Create the same initFileSystem function for playing video
```
function onInitFs(fs) {
  _fs = fs;
  playVideo(fs);
}

function playVideo(fs) {
  //Fetches file from filesystem
  fs.root.getFile(
    filename,
    {},
    function (fileEntry) {
      console.log(fileEntry);

      document.querySelector("#ourVideo").src=fileEntry.fullPath;
      fileEntry.file(function (file) {
        var reader = new FileReader();
        reader.onloadend = function (e) {
          document.querySelector("#ourVideo").play();
        };
        reader.readAsText(file);
      }, errorHandler);
    },
    errorHandler
  );
}
```
Here, `fileEntry.fullPath` creates a filesystem url (`filesystem:http://example:com/temporary/video.mp4`) to fetch video from FileSystem.


Unfortunately, FileSystem is only supported by a few Chromium based browsers (Edge, Chrome, Chrome for Android, Opera, Samsung Internet) and is no longer standardized by W3C. 

I hope that chrome would keep it afloat and other browsers (Firefox, Safari) would implement the same or provide an alternative.