DEV Community

loading...

FileSystem API: Large File Client-Side Storage For Your Website

riyaz7us
Developer with writing and design skills, who likes to build things and keep them minimal yet powerful.
・2 min read

Credits: SyncFusion JS File Manager
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 and StackOverflow

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);
  }
Enter fullscreen mode Exit fullscreen mode

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();
}

Enter fullscreen mode Exit fullscreen mode

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

<video id="ourVideo" controls=""></video>
Enter fullscreen mode Exit fullscreen mode

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
  );
}
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (0)