Skip to content

Instantly share code, notes, and snippets.

@gnitnuj
Last active June 18, 2021 17:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gnitnuj/eb216ab0f687c7d9f3691f2efa7715bb to your computer and use it in GitHub Desktop.
Save gnitnuj/eb216ab0f687c7d9f3691f2efa7715bb to your computer and use it in GitHub Desktop.
module to upload files to s3
const util = require('util');
const AWS = require('aws-sdk');
const path = require('path');
/**
* getClient
* @returns {object} s3 client instance
*/
const getClient = (function() {
let s3Client;
return function() {
if (s3Client) {
return s3Client;
}
s3Client = new AWS.S3({apiVersion: '2006-03-01'});
return s3Client;
};
})();
/**
* listDirectory
* @param {array} accumulator - array to accumulate listed files
* @param {string} bucket - the s3 bucket
* @param {string} prefix - the s3 prefix
* @param {string} lastKey - the last key if the results were truncated
* @returns {list} accumulator
*/
const listDirectory = (list, bucket, prefix, lastKey) => {
if (!list) {
list = [];
}
const s3Client = getClient();
const params = {
Bucket: bucket,
Prefix: prefix,
};
if (lastKey) {
params.NextMarker = lastKey;
}
return util.promisify(s3Client.listObjects.bind(s3Client))(
params,
).then(data => {
const keys = data.Contents.map(item => {
return item.Key;
});
list.push(...keys);
if (data.IsTruncated) {
return listDirectory(list, bucket, prefix, keys[keys.length - 1]);
}
return list;
});
};
module.exports = {
/**
* Check for existing key
* @param {string} bucket
* @param {string} prefix
* @returns {promise}
*/
exists: function(bucket, prefix) {
const s3Client = getClient();
const params = {
Bucket: bucket,
Key: prefix,
};
return util.promisify(s3Client.headObject.bind(s3Client))(params).then(
_ => {
return true;
},
_ => {
return false;
},
);
},
/**
* CleanFolder
* Deletes all items in a folder
* @param {string} bucket
* @param {string} prefix
* @returns {promise}
*/
cleanFolder: function(bucket, prefix) {
const s3Client = getClient();
const deleteObjects = s3Client.deleteObjects.bind(s3Client);
return listDirectory([], bucket, prefix).then(data => {
if (!data.length) {
return;
}
const params = {
Bucket: bucket,
Delete: {
Objects: data.map(key => {
return {Key: key};
}),
},
};
return util.promisify(deleteObjects)(params);
});
},
/**
* Copy a folder located at one prefix to another
* @param {string} bucket
* @param {string} sourcePrefix
* @param {string} destPrefix
* @returns {promise}
*/
copyFolder: function(bucket, sourcePrefix, destPrefix) {
const s3Client = getClient();
const copyObject = s3Client.copyObject.bind(s3Client);
const list = [];
return listDirectory(list, bucket, sourcePrefix).then(data => {
if (!data.length) {
return;
}
return Promise.all(
data.map(key => {
const params = {
Bucket: bucket,
CopySource: path.join('/', bucket, key),
Key: key.replace(sourcePrefix, destPrefix),
ACL: 'public-read',
};
return util.promisify(copyObject)(params);
}),
);
});
},
/**
* uploadFile
* @param {string} bucket
* @param {string} key
* @param {buffer} data
* @param {string} contentType
* @param {string} acl (default='private')
* @returns {promise}
*/
uploadFile: function(bucket, key, body, contentType, acl = 'private', metadata = {}) {
const s3Client = getClient();
const params = {
Bucket: bucket,
ACL: acl,
Key: key,
Body: body,
ContentType: contentType,
Metadata: metadata,
};
return util.promisify(s3Client.putObject.bind(s3Client))(params);
},
};
{
"name": "s3-upload",
"version": "0.2.0"
}
// this file exists just to name the gist, and because gist ordering is asciibetical, it's name starts with a capital letter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment