[]() []() []()
A Node.js module for resizing, and uploading files to Amazon S3 with capability to track progress using websockets.
This module was created to use with little setup and customization as it's simply a wrapper of AWS SDK and gm. This module also utilizes Websockets, which can be optionally enabled to allow the server to send the client messages such as file upload completion and upload progress.
Install package with NPM and add it to your dependencies.
$ npm install s3-image-uploader --save
When you npm install this module - the module dependencies are added (s3, gm, ws), however you'll need to make sure GraphicsMagick is installed on your server. GraphicsMagick is the image manipulation library this module uses.
Also, you'll need to pay attention to how you're server handles timeouts.
I used the following code in my Express application to make sure the post didn't timeout:
app.post('/post-image', function(req, res, next){
res.connection.setTimeout(0); // this could take a while
// code to execute post here
});
Below is the basic configuration, but you can see full example code here
Include the module.
var Uploader = require('s3-image-uploader');
Instantiate the uploader with options. Note that if we didn't want to use websockets functionality - we would add to our options websockets : false
.
Also, note that we're using properties of the user environment, but these could be variables or hard coded if preferred (not ideal for security).
var uploader = new Uploader({
aws : {
key : process.env.NODE_AWS_KEY,
secret : process.env.NODE_AWS_SECRET
},
websocketServer : server,
websocketServerPort : 3004,
});
Width and height options denote the maximum size for the dimension (will be exact if the other dimension is set to 'auto'... but upsizing will not happen). If not defined or set to 'auto' - the dimension will be resized based on aspect ratio of the other. Aspect ratio is always maintained. If square : true
is set and width/height are equal, the smaller dimension will be sized down and the larger will be trimmed off outside of the center.
fileId
is important for the websockets functionality. It's referenced in messages sent to the client about the status. Therefore you may want to use this same identifier as a DOM selector in your client side code (maybe a data attribute) to target visual representations of the messages.
uploader.resize({
fileId : 'someUniqueIdentifier',
width : 600,
height : 'auto',
source : './public/tmp/myoldimage.jpg',
destination : './public/uploads/mynewimage.jpg'
}, function(destination){
console.error('resize success - new image here: ', destination);
// execute success code
}, function(errMsg){
console.error('unable to resize: ', errMsg);
// execute error code
});
This validates the content type referenced in the header of the file.
fileId
is again referenced in messages sent to the client about the status.
if(uploader.validateType(file, fileId, ['image/jpeg', 'image/gif', 'image/png'])) {
console.log('validation passed!');
// execute success code
}
Get the exif data object.
uploader.getExifData(filePath, function(data){
// normally I'd do something with this... like store it in a database
console.log('exif data', data);
});
Get dimension object from image.
The below code will log something like this: { width: 1200, height: 900 }
This method uses the GraphicsMagick size
method. Find more documentation here.
uploader.getSize(filePath, function(data){
console.log('image size data', data);
});
Upload the file to s3.
fileId
is again referenced in messages sent to the client about the status.
uploader.upload({
fileId : 'someUniqueIdentifier',
bucket : 'somebucket',
source : './public/tmp/myoldimage.jpg',
name : 'mynewimage.jpg'
},
function(data){ // success
console.log('upload success:', data);
// execute success code
},
function(errMsg, errObject){ //error
console.error('unable to upload: ' + errMsg + ':', errObject);
// execute error code
});
Delete an array of files from AWS (array can include only one file if desired).
uploader.delete('somebucket', ['cat.jpg', 'dog.png', 'turtle.gif'], function(data){
console.log('yay!', data);
}, function(err){
console.log('fail!', err);
});
s3Params : { 'CacheControl' : 'max-age=3600'}
{ width: 1200, height: 900 }
Please see a full example here.
The most important thing to consider here is that we're receiving fileId
from the server as id
to uniquely identify the upload. We receive message objects via websockets. Below are examples of different messages we might receive on the client.
Error message
{
type : 'error',
id : 'someUniqueIdentifier',
message : 'There was a problem uploading this file.'
}
Upload progress message
{
type : 'progress',
id : 'someUniqueIdentifier',
progressAmount : 5276653, // represents bytes
progressTotal : 6276653 // represents bytes
}
Upload success message
{
type : 'result',
id : 'someUniqueIdentifier',
path : '/mybucket/myimage.jpg'
}
Resize success message
{
type : 'resize',
id : 'someUniqueIdentifier',
size : '100x100'
}
So, a simple implementation of this might look something like this.
Make the websocket connection.
var host = window.document.location.host.replace(/:.*/, '');
var ws = new WebSocket('ws://' + host + ':8080');
Handle messages from the server about the progress of our upload/s and resizing.
ws.onmessage = function(event){
var message = JSON.parse(event.data);
if(typeof message.type !== 'undefined') {
if(message.type === 'progress') // execute code for progress
else if(message.type === 'result') // execute code for result
else if(message.type === 'resize') // execute code for resize status
else if(message.type === 'error') // execute code for error messages
}
};