Darshan
Darshan

Reputation: 1011

How to Upload file to Node.js using Ember Droplet?

I'm using this interface for file uploads on my app:

https://github.com/Wildhoney/EmberDroplet

My app is running on Node.js and Ember is the client-side framework I am working with. I am also required to use Azure Storage service for storing files/images uploads.

However, since I am very new to this concept-wise and tool-wise(Node and Ember, and therefore EmberDroplet), I do not understand how to upload a file through Ember Droplet, then send it to my Node server in order to upload it to Azure.

I have installed the Azure-Storage package and tested it for uploads directly on Node.js. This works.

I have integrated the Ember-Droplet mixin with my interface and it does take files dragged into it or selected via file input.

I do not know how to connect these two: EmberDroplet has a function called uploadallfiles which seems to take the array of files provided as input and create an XHR object out of it, and before it returns its jQuery promise, it sends the XHR request along.

My question is this: How do I set up my application so that when uploadallfiles is executed, my node.js server has access to them so that it can upload them to azure, then store a reference to it in the model the file is associated with?

Follow up question is this: Azure's tutorial on using Azure with node shows how to take a locally stored file via it's filepath and then upload it to Blob Storage. However,

  1. Can client side applications send a local file path to the server and still have this work? I am under the impression that the server-side code has no access to client-side local storage.
  2. Can Azure upload using an XHR instead of a file path?
  3. Is there a specific format that the file needs to be in to be uploaded via azure-storage?

Upvotes: 2

Views: 681

Answers (1)

mpd106
mpd106

Reputation: 768

To answer your questions:

  1. No, the server can't directly access client-side storage--you'll have to post the files themselves to the server (rather than just the paths)
  2. You can upload from client-side javascript straight to Azure, but it's relatively involved. You'd want to generate a Shared Access Signature (SAS) for your client-side code to use as the upload endpoint, and then use jQuery to PUT to that URL. Gaurav Mantri has a great example of this on his blog: http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/
  3. Blob storage is to most intents and purposes very similar to your local filesystem, so there are no major restrictions you'll need to worry about. If your users are uploading files, you should be able to push them directly to blob storage.

With respect to your question about Ember and Ember-Droplet, the Ember-Droplet has some great sample code that shows what you'll need to implement server-side. Take a look at the following excerpt from: https://github.com/Wildhoney/EmberDroplet/blob/master/example/node-server/server.js

// Responsible for handling the file upload.
app.post('/upload', function(request, response) {

    var files       = request.files.file,
        promises    = [];

    /**
     * @method uploadFile
     * @param file {Object}
     * @return {Object}
     */
    var uploadFile = function uploadFile(file) {

        var deferred = new Deferred();

        fileSystem.readFile(file.path, function (error, data) {
            var filePath = __dirname + '/uploaded-files/' + file.name;
            fileSystem.writeFile(filePath, data, function() {});
            deferred.resolve(file.name);
        });

        return deferred.promise;

    };

    if (!Array.isArray(files)) {

        // We're dealing with only one file.
        var promise = uploadFile(files);
        promises.push(promise);

    } else {

        // We're dealing with many files.
        files.forEach(function(file) {
            var promise = uploadFile(file);
            promises.push(promise);
        });

    }

    promisedIo.all(promises).then(function(files) {
        response.send({ files: files, success: true });
        response.end();
    });

});

Obviously that assumes that you're using Express, but in any case it demonstrates that you'll need to implement a post method corresponding to the dropletUrl (as specified in your controller: https://github.com/Wildhoney/EmberDroplet/blob/master/example/scripts/controller.js) to handle receiving the file.

You'll then want to swap out the implementation of uploadFile for something that writes to Azure storage using the Azure node SDK instead. I've put together this little function you could use:

var azure = require('azure-storage');
var blobService = azure.createBlobService('mystorageaccountname', 'mystorageaccountkey', 'https://mystorageaccountname.blob.core.windows.net');

var uploadFile = function(file) {
    var deferred = new Deferred();

    blobService.createBlockBlobFromFile('mycontainername', file.name, file.path, function(error, result, response) {
        if (!error) {
            deferred.resolve(file.name);
        }
    });

    return deferred.promise;
};

If you drop that function into the Ember-Droplet example server implementation in place of the existing one, you'll end up with the server writing your files to blob storage. Note that you'll need to use a valid storage account name, storage account key and blob container name in place of the placeholders above (including in the host string specified in the call to azure.createBlobService).

Upvotes: 7

Related Questions