Skip to content

Instantly share code, notes, and snippets.

@francolaiuppa
Last active April 21, 2023 17:31
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save francolaiuppa/76f4b60cd46a15d325cf to your computer and use it in GitHub Desktop.
Save francolaiuppa/76f4b60cd46a15d325cf to your computer and use it in GitHub Desktop.
Express JS + Amazon S3 + DropzoneJS Code Snippet
// Requires https://www.npmjs.org/package/s3-policy and https://www.npmjs.org/package/node-uuid
var config = require('env/' + process.env.NODE_ENV),
policy = require('s3-policy'),
uuid = require('node-uuid');
// SETUP S3
const AWS_ACCESS_KEY = config.s3.accessKey;
const AWS_SECRET_KEY = config.s3.secret;
const S3_BUCKET = config.s3.bucket;
// PRIVATE METHODS
function _getExtension(filename) {
var i = filename.lastIndexOf('.');
return (i < 0) ? '' : filename.substr(i);
}
// PUBLIC METHODS
exports.signS3 = function signS3(req, res) {
var fileExtension = _getExtension(req.body.name),
filename = uuid.v4() + fileExtension,
acl = 'public-read',
p = policy({
acl: acl,
secret: AWS_SECRET_KEY,
length: 5000000, // in bytes?
bucket: S3_BUCKET,
key: filename,
expires: new Date(Date.now() + 60000),
}),
result = {
'AWSAccessKeyId': AWS_ACCESS_KEY,
'key': filename,
'policy': p.policy,
'signature': p.signature
};
res.write(JSON.stringify(result));
res.end();
};
var app = {};
app.signS3RequestURL = '/admin/S3/sign';
app.S3_BUCKET = 'http://your-bucket-name.s3.amazonaws.com/';
app._dropzoneAcceptCallback = function _dropzoneAcceptCallback(file, done) {
file.postData = [];
$.ajax({
url: app.signS3RequestURL,
data: {
name: file.name,
type: file.type,
size: file.size,
_csrf: $('#__createPostToken').val() // this is not needed to make Dropzone work, it's express related
},
type: 'POST',
success: function jQAjaxSuccess(response) {
response = JSON.parse(response);
file.custom_status = 'ready';
file.postData = response;
file.s3 = response.key;
$(file.previewTemplate).addClass('uploading');
done();
},
error: function(response) {
file.custom_status = 'rejected';
if (response.responseText) {
response = JSON.parse(response.responseText);
}
if (response.message) {
done(response.message);
return;
}
done('error preparing the upload');
}
});
};
app._dropzoneSendingCallback = function(file, xhr, formData) {
$.each(file.postData, function(k, v) {
formData.append(k, v);
});
formData.append('Content-type', '');
formData.append('Content-length', '');
formData.append('acl', 'public-read');
};
app._dropzoneCompleteCallback = function(file) {
var inputHidden = '<input type="hidden" name="attachments[]" value="';
var json = {
url: app.S3_BUCKET + file.postData.key,
originalFilename: file.name
};
console.log(json, JSON.stringify(json), JSON.stringify(json).replace('"', '\"'));
inputHidden += window.btoa(JSON.stringify(json)) + '" />';
$('form#createPost').append(inputHidden);
}
app.setupDropzone = function setupDropzone() {
if ($('div#dropzone').length === 0) {
return;
}
Dropzone.autoDiscover = false;
app.dropzone = new Dropzone("div#dropzone", {
url: app.S3_BUCKET,
method: "post",
autoProcessQueue: true,
clickable: true,
maxfiles: 5,
parallelUploads: 3,
maxFilesize: 10, // in mb
maxThumbnailFilesize: 8, // 3MB
thumbnailWidth: 150,
thumbnailHeight: 150,
acceptedMimeTypes: "image/bmp,image/gif,image/jpg,image/jpeg,image/png",
accept: app._dropzoneAcceptCallback,
sending: app._dropzoneSendingCallback,
complete: app._dropzoneCompleteCallback
});
};
app.startup = function startup() {
app.setupDropzone();
}
$(document).ready(app.startup);
@cbrammer
Copy link

+1 Thanks for this, worked like a charm

@joeabill
Copy link

Thank you sir, worked for me!

@francolaiuppa
Copy link
Author

Thank you guys! I never saw these notifications.
In case anyone stumbles upon this, I wrote a more detailed explanation here

@phoet
Copy link

phoet commented Apr 27, 2015

what exactly is the file.custom_status used for?

@shaharsol
Copy link

Wow this was SO useful!

@cyurtbil
Copy link

best example I've ever seen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment