Reputation:
I'm using AWS SDK for Node.js to create a folder or key on s3. I searched on google, but I got nothing. Does anybody know how can I create a folder under my bucket with AWS SDK for Node.js? and how can you check if this folder exists in your bucket already?
if you use console.aws.amazon.com
, you can create a folder in your bucket easily. it seems I didn't figure it out how to create it with AWS SDK for Node.js?
Upvotes: 58
Views: 91818
Reputation: 78793
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/");
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:
listObjects
with prefix=cars/ford/
and find it in Contents
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.
Upvotes: 117
Reputation: 2321
This is really straightforward you can do it by using the following, just remember the trailing slash.
var AWS = require("aws-sdk");
var s3 = new AWS.S3();
var params = {
Bucket: "mybucket",
Key: "mykey/"
};
s3.putObject(params).promise();
Upvotes: 12
Reputation: 31
In console, the link generated first would be the bucket created path and second would be the folder structure.
var AWS = require("aws-sdk");
var path = require('path')
// Set the region
AWS.config.update({
region: "us-east-2",
accessKeyId: "your aws acces id ",
secretAccessKey: "your secret access key"
});
s3 = new AWS.S3();
var bucketParams = {
Bucket: "imageurrllll",
ACL: "public-read"
};
s3.createBucket(bucketParams, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Location);
var folder_name = 'root_folder'
//this is for local folder data path
var filePath = "./public/stylesheets/user.png"
//var child_folder='child'
var date = Date.now()
var imgData = `${folder_name}_${date}/` +
path.basename(filePath);
var params = {
Bucket: 'imageurrllll',
Body: '', //here you can give image data url from your local directory
Key: imgData,
ACL: 'public-read'
};
//in this section we are creating the folder structre
s3.upload(params, async function(err, aws_uploaded_url) {
//handle error
if (err) {
console.log("Error", err);
}
//success
else {
console.log("Data Uploaded in:", aws_uploaded_url.Location)
}
})
}
});
Upvotes: -2
Reputation: 310
I find that we do not need an explicit directory creation call anymore.
Just the following works for me and automatically creates a directory hierarchy as I need.
var userFolder = 'your_bucket_name' + '/' + variable-with-dir-1-name + '/' + variable-with-dir-2-name;
// IMPORTANT : No trailing '/' at the end of the last directory name
AWS.config.region = 'us-east-1';
AWS.config.update({
accessKeyId: 'YOUR_KEY_HERE',
secretAccessKey: 'your_secret_access_key_here'
});
var bucket = new AWS.S3({
params: {
Bucket: userFolder
}
});
var contentToPost = {
Key: <<your_filename_here>>,
Body: <<your_file_here>>,
ContentEncoding: 'base64',
ContentType: <<your_file_content_type>>,
ServerSideEncryption: 'AES256'
};
bucket.putObject(contentToPost, function (error, data) {
if (error) {
console.log("Error in posting Content [" + error + "]");
return false;
} /* end if error */
else {
console.log("Successfully posted Content");
} /* end else error */
})
.on('httpUploadProgress',function (progress) {
// Log Progress Information
console.log(Math.round(progress.loaded / progress.total * 100) + '% done');
});
Upvotes: 8
Reputation: 3784
The code from @user2837831 doesn't seem to work anymore, probably with the new version of javascript sdk. So I am adding here the version of code that I am using to create a folder inside a bucket using node.js. This works with the 2.1.31 sdk. What is important is the '/' at the end of the Key value in params - using that it thinks you are trying to create a folder and not a file.
var AWS = require('aws-sdk');
AWS.config.region = 'us-east-1';
var s3Client = new AWS.S3();
var params = { Bucket: 'your_bucket_goes_here', Key: 'folderInBucket/', ACL: 'public-read', Body:'body does not matter' };
s3Client.upload(params, function (err, data) {
if (err) {
console.log("Error creating the folder: ", err);
} else {
console.log("Successfully created a folder on S3");
}
});
Upvotes: 33