Web Development

Uploading Files In Sails.js

Uploading files in Sails.js is quite simple and is actually well documented via the Sail.js documentation. What isn’t documented is handling the file after the upload. Most of the time if a file is uploaded, such as an image, we want to use it immediately as a profile picture or so it can be viewed in a gallery. The problem in Sails.js is that images and other assets are cached during the server lift. Thus, when you upload a file it isn’t available to the application to be referenced. To solve this problem there are two options. First, the most recommended method is to use a cloud service to host the file, which takes the load/storage off your server. The second, is copying the asset into the .tmp directory in your Sails.js project so that it will become available immediately.

I’d like to cover the second option as there are many cloud services that can be integrated to store files for a Sails.js or more generically a node.js project. However, there are two caveats to be addressed in this method:

  • Images must be stored in the assets folder of the application for the images to be made available.
  • The .tmp folder is cleared if the server is shutdown.

The easiest way to over come this is to copy the files into the .tmp directory after they are uploaded to the assets folder. In this way, when the server is shutdown the files are cached because they originate in the assets folder thus are automatically copied over. Likewise, since they are copied to the .tmp folder initially they become available right away.
The following is a simple controller method to handle uploads.

upload: function(req, res){

        if (req.method === 'POST') {

            req.file('filename').upload({dirname : process.cwd() + '/assets/images/uploads/'}, function (err, uploadedFiles) {
              if (err) return res.send(500, err);

                var filename = uploadedFiles[0].fd.substring(uploadedFiles[0].fd.lastIndexOf('/')+1);
                var uploadLocation = process.cwd() +'/assets/images/uploads/' + filename;
                var tempLocation = process.cwd() + '/.tmp/public/images/uploads/' + filename;

                //Copy the file to the temp folder so that it becomes available immediately

                //Redirect or do something
        } else {

It is also possible to modify your Grunt file in order to not store the images in a public directory, but still allow them to be exposed, however, they again become publicly exposed once copied over during the server lift.