@ashkiani/s3-file-utils
Version:
List files in an S3 folder and generate signed URLs using AWS SDK v3.
99 lines (87 loc) • 3.41 kB
JavaScript
const { S3Client, ListObjectsV2Command, GetObjectCommand } = require('@aws-sdk/client-s3');
const s3Client = new S3Client({ region: process.env.AWS_REGION });
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
/**
* Lists all the files in a specific folder (prefix) inside an S3 bucket and returns them sorted alphabetically.
*
* @param {string} bucketName - The name of your S3 bucket.
* @param {string} folderPath - The folder path (prefix) within the bucket. Ensure it ends with a '/'.
* @returns {Promise<string[]>} - A promise that resolves to an array of file keys sorted alphabetically.
*/
// stream -> string helper
async function streamToString(stream) {
return await new Promise((resolve, reject) => {
const chunks = [];
stream.on('data', (c) => chunks.push(Buffer.from(c)));
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
});
}
// get S3 object as UTF-8 text
async function getObjectText(bucket, key) {
const res = await s3Client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
return await streamToString(res.Body);
}
// parse JSON from S3 (removes BOM before parsing)
async function getJson(bucket, key) {
const text = await getObjectText(bucket, key);
const clean = text.replace(/^\uFEFF/, ''); // strip UTF-8 BOM if present
return JSON.parse(clean);
}
async function listFilesInFolder(bucketName, folderPath) {
let fileKeys = [];
let isTruncated = true;
let continuationToken;
const params = {
Bucket: bucketName,
Prefix: folderPath,
Delimiter: '/',
};
try {
while (isTruncated) {
// Copy the parameters and add the ContinuationToken if available
const commandParams = { ...params };
if (continuationToken) {
commandParams.ContinuationToken = continuationToken;
}
const command = new ListObjectsV2Command(commandParams);
const data = await s3Client.send(command);
if (data.Contents) {
data.Contents.forEach(item => {
// Filter out the folder itself and any subfolder markers (ending with '/')
if (item.Key !== folderPath && !item.Key.endsWith('/')) {
fileKeys.push(item.Key);
}
});
}
isTruncated = data.IsTruncated;
continuationToken = data.NextContinuationToken;
}
// Sort the file keys in alphabetical order
fileKeys.sort();
const fileNames = fileKeys
.map(key => key.substring(folderPath.length))
.sort();
return fileNames;
} catch (error) {
console.error("Error listing files from S3:", error);
throw error;
}
}
async function genSignedUrl(bucket, file) {
// Generate a pre-signed URL for the S3 object.
const params = {
Bucket: bucket,
Key: file
};
const command = new (require('@aws-sdk/client-s3').GetObjectCommand)(params);
//console.log("Command input:", command.input);
const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: process.env.URL_EXPIRES_IN });
return signedUrl
}
module.exports = {
listFilesInFolder,
genSignedUrl,
getObjectText,
getJson,
};