39
votes

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?

5

5 Answers

83
votes

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:

  1. call listObjects with prefix=cars/ford/ and find it in Contents
  2. 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.

26
votes

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");

    }
});
7
votes

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');
});
6
votes

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();
-2
votes

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)

      }

    })
  }

});