AWS SDK v3 Solutions
Here are some useful Node.js functions for AWS SDK v3:
const {
S3Client,
PutObjectCommand,
HeadObjectCommand,
DeleteObjectCommand,
} = require("@aws-sdk/client-s3");
async function createFolder(Bucket, Key) {
const client = new S3Client();
const command = new PutObjectCommand({ Bucket, Key });
return client.send(command);
}
async function existsFolder(Bucket, Key) {
const client = new S3Client();
const command = new HeadObjectCommand({ Bucket, Key });
try {
await client.send(command);
return true;
} catch (error) {
if (error.name === "NotFound") {
return false;
} else {
throw error;
}
}
}
async function createFolderIfNotExist(Bucket, Key) {
if (!(await existsFolder(Bucket, Key))) {
return createFolder(Bucket, Key);
}
}
async function deleteFolder(Bucket, Key) {
const client = new S3Client();
const command = new DeleteObjectCommand({ Bucket, Key });
return client.send(command);
}
Examples of using these functions:
const exists1 = await existsFolder("mybucket", "myfolder/");
const exists2 = await existsFolder("mybucket", "pets/dogs/");
if (!exists2) await createFolder("mybucket", "pets/dogs/");
Notes on S3 Object Store
S3 is not your typical file system. It's an object store. It has buckets and objects. Buckets are used to store objects, and objects comprise data (basically a file) and metadata (information about the file). When compared to a traditional file system, it's more natural to think of an S3 bucket as a drive rather than as a folder.
You don't need to pre-create a folder structure in an S3 bucket. You can simply put an object with the key cars/ford/focus.png
even if cars/ford/
does not exist.
It's valuable to understand what happens at the API level in this case:
the putObject call will create an object at cars/ford/focus.png
but it will not create anything representing the intermediate folder structure of cars/
or cars/ford/
.
the actual folder structure does not exist, but is implied through delimiter=/
when you call listObjects, returning folders in CommonPrefixes
and files in Contents
.
you will not be able to test for the ford sub-folder using headObject because cars/ford/
does not actually exist (it is not an object). Instead you have 2 options to see if it (logically) exists:
- call
listObjects
with prefix=cars/ford/
and find it in Contents
- call
listObjects
with prefix=cars/
, delimiter=/
and find it in CommonPrefixes
It is possible to create an S3 object that represents a folder, if you really want to. The AWS S3 console does this, for example. To create myfolder in a bucket named mybucket, you can issue a putObject call with bucket=mybucket, key=myfolder/, and size 0. Note the trailing forward slash.
Here's an example of creating a folder-like object using the awscli:
aws s3api put-object --bucket mybucket --key cars/ --content-length 0
In this case:
the folder is actually a zero-sized object whose key ends in /. Note that if you leave off the trailing / then you will get a zero-sized object that appears to be a file rather than a folder.
you are now able to test for the presence of cars/ in mybucket by issuing a headObject call with bucket=mybucket and key=cars/.
Finally, note that your folder delimiter can be anything you like, for example +, because it is simply part of the key and is not actually a folder separator (there are no folders). You can vary your folder delimiter from listObjects call to call if you like.