Quick Tip: Is there sufficient storage space available on the device?

There was a post on the Google Group for PhoneGap a few days ago that was asking if there was a way to determine how much free space was available on the mobile device. As it turns out, there’s a few answers to this question, some less tenable than others. Let’s start with the safest and preferred option (in my opinion).

The Preferred Method

NOTE: The snippets below require the cordova-plugin-file plugin.

When requesting a file system, you can ask for the number of bytes you think you’ll need. If the file plugin can’t meet the request, you’ll get a QUOTA_EXCEEDED_ERR (code 10). If there is enough space, you’ll be passed a file system as usual.

For example, the following snippet is pretty much guaranteed to fail for a while — at least until mobile devices carry more than a terabyte of storage:

window.requestFileSystem(LocalFileSystem.PERSISTENT, 1024*1024*1024*1024,
                         function success(fs) {
                             alert("Got file system" + JSON.stringify(fs));
                         }, function error(e) {
                             alert("Got error" + JSON.stringify(e));
                         });
// This is almost certainly going to fail with {code: 10}

Conceivably, one could make a convenience utility that looked like the following:

function isThereSufficientSpace(spaceNeeded) {
    return new Promise(function (resolve, reject) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, spaceNeeded,
                                 resolve, reject);
    });
}

// could use like this:
isThereSufficientSpace(5*1024*1024)
    .then(writeABigFile)
    .catch(handleError);

Of course, just because there was enough space when you started your operation doesn’t mean that something else on the device won’t be using up space. If you’re using a FileWriter, you need to be on the lookout for the same QUOTA_EXCEEDED_ERR. Using the example from the plugin documentation, it might look like the following (my changes are lines 11 through 16):

function writeFile(fileEntry, dataObj) {
    // Create a FileWriter object for our FileEntry (log.txt).
    fileEntry.createWriter(function (fileWriter) {

        fileWriter.onwriteend = function() {
            console.log("Successful file read...");
            readFile(fileEntry);
        };

        fileWriter.onerror = function (e) {
            // What error did we get?
            if (e.code === 10) {
                // Uh oh, we're out of space
                alert("Your device is out of space; please delete some files or apps in order to free space.");
                // ideally, you'd proceed to clean up your own files that you can restore (cache, tmp, etc.) and
                // try again before complaining to the user
            }
            console.log("Failed file read: " + e.toString());
        };

        // If data object is not passed in,
        // create a new Blob instead.
        if (!dataObj) {
            dataObj = new Blob(['some file data'], { type: 'text/plain' });
        }

        fileWriter.write(dataObj);
    });
}

Here Be Dragons

However, let’s say you really do need the exact number of bytes available on the user’s device for some reason. The file plugin does currently have a way of retrieving this information, but it’s not exposed via the JavaScript API. As such (and based on the discussion on the CB-6703), I’d consider using this method to be very risky — one that could go away or change at any time, and may not even work on all platforms. Don’t use it in Production code!

If you’re willing to play in very murky waters (here be dragons — don’t say I didn’t warn you), though, you can visit Nic Raboy’s (The PolyGlot Developer) post on how exactly to get the number of free bytes. I tried it on my device, and it worked for me. Of course, that doesn’t mean it will work for you, for any other platform, or even for any length of time into the future. Which is why I wouldn’t use it in my production apps. But for completeness sake, I wanted to mention it.

Use a Third-Party Plugin

Another option, assuming you don’t mind a third-party plugin, is sqli-cordova-disk-space-plugin. I haven’t tried it myself, but based on the documentation, it looks like it should do the trick. It also supplies total space and the space used by your app. But before you use it, I’d think long and hard about whether you really need this much information in the first place.

Final Thoughts

How often do we ever really need to know exactly how much space is available on the user’s device? If one were developing some sort of file manager and wished to show remaining space available, I could see the need, but that’s not the typical use case. Typically all we want to know is “will this file I’m about to create or download fit?” We don’t typically need to know how close the fit will be, we just need a binary “yes” or “no” answer. As such, I’d highly suggest using “The Preferred Method” above.

Thoughts, comments? Leave them in the comment section below! I always love hearing from the PhoneGap community!

Leave a Reply