name
name

Reputation: 235

how do I rename a folder?

I want to do this with aws-sdk library.

I have a folder on my S3 bucket called "abcd/", it has 3 files on it (e.g. abcd/1.jpg, abcd/2.jpg).

I want to rename the folder to 1234/

enter image description here

^ I want there to be 1234/ only

const awsMove = async (path) => {
  try {
    const s3 = new AWS.S3();
    const AWS_BUCKET = 'my-bucket-test';

    const copyParams = {
      Key: path.newPath,
      Bucket: AWS_BUCKET,
      CopySource: encodeURI(`/${AWS_BUCKET}/${path.oldPath}`),
    };
    await s3.copyObject(copyParams).promise();

    const deleteParams = {
      Key: path.oldPath,
      Bucket: AWS_BUCKET,
    };
    await s3.deleteObject(deleteParams).promise();
  } catch (err) {
    console.log(err);
  }
};

const changePath = { oldPath: 'abcd/', newPath: '1234/' };
awsMove(changePath);

The above code errors with "The specified key does not exist" what am I doing wrong?

Upvotes: 2

Views: 1171

Answers (2)

vaquar khan
vaquar khan

Reputation: 11449

Unfortunately, you will need to copy the old ones to the new name and delete them from the old one.

BOTO 3:

    AWS_BUCKET ='my-bucket-test'

    s3 = boto3.resource('s3')
    s3.Object(AWS_BUCKET,'new_file').copy_from(CopySource='AWS_BUCKET/old_file')
    s3.Object(AWS_BUCKET,'old_file').delete()

Node :

    var s3 = new AWS.S3();

    AWS_BUCKET ='my-bucket-test'
    var OLD_S3_KEY = '/old-file.json';
    var NEW_S3_KEY = '/new-file.json';

    s3.copyObject({
      Bucket: BUCKET_NAME, 
      CopySource: `${BUCKET_NAME}${OLD_KEY}`, 
      Key: NEW_KEY
     })
      .promise()
      .then(() => 
        s3.deleteObject({
          Bucket: BUCKET_NAME, 
          Key: OLD_KEY
        }).promise()
       )
      .catch((e) => console.error(e))

Upvotes: 0

Rahul Sharma
Rahul Sharma

Reputation: 5995

AWS S3 does not have the concept of folders as in a file system. You have a bucket and a key that identifies the object/file stored at that location. The pattern of the key is usually a/b/c/d/some_file and the way it is showed on AWS console, it might give you an impression that a, b, c or d are folders but indeed they aren't.

Now, you can't change the key of an object since it is immutable. You'll have to copy the file existing at the current key to the new key and delete the file at current key.

This implies renaming a folder say folder/ is same as copying all files located at key folder/* and creating new ones at newFolder/*. The error:

The specified key does not exist

says that you've not specified the full object key during the copy from source as well as during deletion. The correct implementation would be to list all files at folder/* and copy and delete them one by one. So, your function should be doing something like this:

const awsMove = async (path) => {
  try {
    const s3 = new AWS.S3();
    const AWS_BUCKET = 'my-bucket-test';

    const listParams = { 
      Bucket: AWS_BUCKET,
      Delimiter: '/',
      Prefix: `${path.oldPath}`
    }

    await s3.listObjects(listParams, function (err, data) {
      if(err)throw err;

      data.Contents.forEach(async (elem) => {
        const copyParams = {
          Key: `${path.newPath}${elem.Key}`,
          Bucket: AWS_BUCKET,
          CopySource: encodeURI(`/${AWS_BUCKET}/${path.oldPath}/${elem.Key}`),
        };
        await s3.copyObject(copyParams).promise();

        const deleteParams = {
          Key: `${path.newPath}${elem.Key}`,
          Bucket: AWS_BUCKET,
        };
        await s3.deleteObject(deleteParams).promise();
      });
    }).promise();
  } catch (err) {
    console.log(err);
  }
};

Upvotes: 5

Related Questions