Secure File API

Sencha Web Application Client provides an encrypted file system where applications can store files. These files are isolated from all other applications in the user’s organization. Files stored in one application cannot be read by or written to from another application.

SecureFiles

To make reading and writing files easy, Sencha Web Application Client exposes a simple key/value store for files. This API is optimized for the common file operations of read, write, and list.

Each SecureFiles collection essentially represents a named “bucket” of files; to create or fetch a collection, we use the Ext.space.SecureFiles API:

Ext.onSpaceReady().then(function() {

    var collection = Ext.space.SecureFiles.get('secrets');

});

Once we have a collection, we simply get/set values to read/write contents. Collection methods return promises, so we run code the typical way:

collection.get('users.txt').then(function(contents) {
    // do something with the contents
});

collection.set({ name:'groups.txt', type:'text/plain'}, 'Placeholder!').then(function(file) {
    // done!
});

Note the file parameter to the promise callback in the .set snippet. That’s an instance of Ext.space.files.File, an object that Sencha Web Application Client uses to encapsulate file metadata. It’s got a few properties like .type for the MIME type, .created for the creation date, and so forth, but for the most part, we treat it as a simple container object with shortcut methods to give us access to functionality like loading contents, viewing the file, and so forth.

For example, we can query our collection to get a list of the files available, and then conditionally load the contents of the ones in which we are interested:

var myFiles = [{
    name: "foo.txt"
}, {
    name: "bar.txt"
}];

// fetch every file
collection.query().then(function(files) {
    // create a list of the names we're interested in
    var myFileNames = myFiles.map(function(f) {
       return f.name;
    });

    files.forEach(function(file) {
       // is this file interesting, i.e., is it in myFiles?
       var pos = myFileNames.indexOf(file.name);
       if (pos > -1) {
         // retrieve the contents
         file.getContents().then(function(contents) {
          // store the contents in the original array
          myFiles[pos].contents = contents;
         });
       }
    });
});

The query method does more than simply list files; it can also filter them. For one example:

var aWeekAgo = new Date((new Date).getTime() - (1000 * 60 * 60 * 24 * 7));

// retrieve all text files created within the past week
collection.query({ createdAfter: aWeekAgo, type: 'text/plain'}).then(function(files) {
    // do something with them
});

Sencha Web Application Client makes it easy to launch the file viewer for a particular file; just pass the file name:

collection.view('legal.txt').then(function() {
    // viewer launched!
});

Finally, Sencha Web Application Client has built in support for uploading files to a form processor:

collection.query('avatar.jpg').then(function(avatarFile) {
    avatarFile.upload({
       url: "http://example.com/avatarForm", // form processor URL
       fileFieldName: "imgfile"              // name of the form field to use
    }).then(function(response) {
       // inspect the response
    });
});

Those are the basics, but there is a lot more. See Ext.space.SecureFiles for more details on the API.

SecureFiles Example

For a more realistic demonstration of the APIs, we also provide the SecureFiles example application in our github repository: https://github.com/sencha/SpaceExamples/tree/master/SecureFiles.

In the SecureFiles example we use our camera API to fetch files from the phone’s library and store them in the application’s encrypted filesystem. The images are then retrieved and displayed in a list.

First, we need to create a collection where we want to store all of the photos. Think of collections as folders, an application can have as many folders as it needs. If a collection does not exist it’s automatically created:

Ext.onSpaceReady().then(function() {

    photos = Ext.space.SecureFiles.get('photos');

});

Next, to fetch a photo from the user’s library, we use the Ext.space.Camera API:

var result = Ext.space.Camera.capture({
        quality: 75,
        width: 200,
        height: 200,
        source: 'library',
        encoding: 'jpeg',
        destination: 'data'
});

In the above code we create a 200x200 pixel thumbnail of the selected image before storing it. By specifying the destination as ‘data’, we instruct the capture call to return the image data as a base-64 encoded string.

When the promise returns, we can store the image by calling a set on the photos collection:

result.then(function(image) {
    log("user chose image");
    photos.set(new Date().getTime()+".jpg", image).then(function() {
        log("image saved");
        loadImageList();
    });
})

Next, to display all of the photos in the collection, we use Ext.space.files.Collection.keys:

photos.keys().then(function(fileNames) {
    log("image count: " + fileNames.length);
    if(fileNames.length == 0) {
        div.innerHTML = "No Images";
    }
    for(var i =0, l = fileNames.length; i<l; i++) {
        photos.get(fileNames[i]).then(function(content) {
            var img = document.createElement("img");
            img.src = "data:image/jpeg;base64," + content;
            div.appendChild(img);
        });
    }
});

In this code, we loop over each of the image file names and fetch the contents of each photo. Once we have the contents of the photo we create a data URI and assign it to the source of an image.

For complete source code, see https://github.com/sencha/SpaceExamples/tree/master/SecureFiles.

Last updated