Serverless Download

I have a little time-tracking tool that I have been using to track my billable time.  The program stores everything in the local storage within the browser.  The challenge comes when I want to export or backup the information stored in the browser.  I don’t want to force the user to send the data to my website just so it can turn around and download it back to the user’s hard drive.

Here’s the solution that I came up with:

First, I created a text area to store the data.  This is a simple solution because the user can copy it out and do anything he wants.

<textarea id='dataOutput' style='width:100%'></textarea>

Next, I created a basic object and I added the data to properties on the object.  I didn’t include the “storageModel” object because it’s a little out of scope for this article.  Basically, it’s responsible for writing to and reading from the local storage in the browser.  Here’s the object with the data …

var o = {};

var e = storageModel.loadEmployers();
 o.employers = e;

var c = storageModel.loadClients();
 o.clients = c;

var s = storageModel.loadSubClients();
 o.subClients = s;

Next, I used the JSON library to convert the object to a JSON formatted string.  And, I used jQuery to set the value of my text area with that string:


$('#dataOutput').val(JSON.stringify(o));

I just discovered that the JSON library has multiple parameters that allow you to format it.  So, I added the 3rd parameter to tell it to indent with 4 spaces.

$('#dataOutput').val(JSON.stringify(o, null, 4));

Then, I used this code to generate the data URL.  The goal is to create a download link with the URL:


window.URL = window.URL || window.webkiURL;
 var blob = new Blob([JSON.stringify(o, null, 4)]);
 var blobURL = window.URL.createObjectURL(blob);

Then, I used this code to add a link to the page after the text area.  The download attribute is what makes it prompt for a place to save the file rather than just loading it into the browser as a new tab.


$("<a></a>").
 addClass("btn").
 attr("href", blobURL).
 attr("download", "completeBackup.json").
 text("Download Data").
 insertAfter('#dataOutput');

Finally, I have been converting my application to use Angular.js.  So, I changed the code up just a little.  Here’s the HTML view:


<div ng-show="backupTextData">
 <textarea ng-model="backupTextData"></textarea>
 <a class="btn" href="{{backupURL}}" download="completeBackup.json">Download Data</a>
 </div>

And, I changed my code to update properties on the scope:


$scope.backupTextData = JSON.stringify(o, null, 4);

window.URL = window.URL || window.webkiURL;
 var blob = new Blob([$scope.backupTextData]);
 $scope.backupURL = window.URL.createObjectURL(blob);

All in all, it seems to get the job done.

Resources

Leave a Comment

Your email address will not be published. Required fields are marked *