Skip to content

Instantly share code, notes, and snippets.

@SylarRuby
Last active November 4, 2023 13:53
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
  • Save SylarRuby/b60eea29c1682519e422476cc5357b60 to your computer and use it in GitHub Desktop.
Save SylarRuby/b60eea29c1682519e422476cc5357b60 to your computer and use it in GitHub Desktop.
NodeJs AWS S3 Upload
/**
* This gist was inspired from https://gist.github.com/homam/8646090 which I wanted to work when uploading an image from
* a base64 string.
* Updated to use Promise (bluebird)
* Web: https://mayneweb.com
*
* @param {string} base64 Data
* @return {string} Image url
*/
const imageUpload = async (base64) => {
// You can either "yarn add aws-sdk" or "npm i aws-sdk"
const AWS = require('aws-sdk');
// Configure AWS with your access and secret key.
const { ACCESS_KEY_ID, SECRET_ACCESS_KEY, AWS_REGION, S3_BUCKET } = process.env;
// Configure AWS to use promise
AWS.config.setPromisesDependency(require('bluebird'));
AWS.config.update({ accessKeyId: ACCESS_KEY_ID, secretAccessKey: SECRET_ACCESS_KEY, region: AWS_REGION });
// Create an s3 instance
const s3 = new AWS.S3();
// Ensure that you POST a base64 data to your server.
// Let's assume the variable "base64" is one.
const base64Data = new Buffer.from(base64.replace(/^data:image\/\w+;base64,/, ""), 'base64');
// Getting the file type, ie: jpeg, png or gif
const type = base64.split(';')[0].split('/')[1];
// Generally we'd have an userId associated with the image
// For this example, we'll simulate one
const userId = 1;
// With this setup, each time your user uploads an image, will be overwritten.
// To prevent this, use a different Key each time.
// This won't be needed if they're uploading their avatar, hence the filename, userAvatar.js.
const params = {
Bucket: S3_BUCKET,
Key: `${userId}.${type}`, // type is not required
Body: base64Data,
ACL: 'public-read',
ContentEncoding: 'base64', // required
ContentType: `image/${type}` // required. Notice the back ticks
}
// The upload() is used instead of putObject() as we'd need the location url and assign that to our user profile/database
// see: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property
let location = '';
let key = '';
try {
const { Location, Key } = await s3.upload(params).promise();
location = Location;
key = Key;
} catch (error) {
// console.log(error)
}
// Save the Location (url) to your database and Key if needs be.
// As good developers, we should return the url and let other function do the saving to database etc
console.log(location, key);
return location;
// To delete, see: https://gist.github.com/SylarRuby/b3b1430ca633bc5ffec29bbcdac2bd52
}
module.exports = imageUpload;
@savtwo
Copy link

savtwo commented Jan 18, 2018

Exactly what I was looking for the past few days. Cheers!

@bishoymelek-zz
Copy link

thanks a lot helped me today!

@sarfarazansari
Copy link

@SylarRuby,
I took the reference from your gist and made it work with any kind of file. in fact with chunks data.
here is the link https://gist.github.com/sarfarazansari/59d5cf4bb3b03acf069396ca92a79b3e

@frozenwine
Copy link

Is it possible to upload a file into subdirectory? Such as: MY_S3_BUCKET/A_DIRECTORY?

@ChunAllen
Copy link

ChunAllen commented Nov 23, 2018

Thanks for this. Just want to add if you already have a file data you can simply pass it in the body params of s3.upload since s3 sdk accepts blob file

this.profileImage is a blob file

const params = { Bucket: 'bucket-name,  Key: this.profileImage.name, Body: this.profileImage };
      s3.upload(params, (err,data) => {
        if (err) { return console.log(err) }
        console.log('Image successfully uploaded.');
        console.log(data.Location); // returns the url of uploaded image
 });

@SylarRuby
Copy link
Author

Is it possible to upload a file into subdirectory? Such as: MY_S3_BUCKET/A_DIRECTORY?

Anything is possible. I need to make an updated revision and I'll have a look then.

@SylarRuby
Copy link
Author

Thanks for this. Just want to add if you already have a file data you can simply pass it in the body params of s3.upload since s3 sdk accepts blob file

this.profileImage is a blob file

const params = { Bucket: 'bucket-name,  Key: this.profileImage.name, Body: this.profileImage };
      s3.upload(params, (err,data) => {
        if (err) { return console.log(err) }
        console.log('Image successfully uploaded.');
        console.log(data.Location); // returns the url of uploaded image
 });

I'm not sure what you mean. I will have another write up on this topic in a few days. Hopefully I will then understand what you're trying to achieve.

@jaredstevick
Copy link

This is great! Thank you! 👍

@passandscore
Copy link

Thank you very much. This is just the thing I was looking for.

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