0

In AWS SDK Version 2 I was uploading files to S3 and getting their public url in reposonse.

// using ASW SDK version 2

var S3 = require('aws-sdk/clients/s3')

var s3 = new S3({
    accessKeyId: config.aws.accessKeyId,
    secretAccessKey: config.aws.secretAccessKey,
    region: config.aws.region,
    apiVersion: '2010-12-01'
});

var uploadToS3 = async function(uploadParams) {
    var response = await s3.upload(uploadParams).promise()
    return response.Location
}

It was so easy to get url of file after uploading using response.Location.

Now I have started using AWS SDK for S3 version 3 for doing same thing but I did not find way to get url after uploading file.

// using AWS SDK version 3
const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3");

var awsCredentials = {
    region: config.aws.region,
    credentials: { accessKeyId: config.aws.accessKeyId, secretAccessKey: config.aws.secretAccessKey }
}
var s3Client = new S3Client(awsCredentials)

var uploadToS3 = async function (uploadParams) {
    const data = await s3Client.send(new PutObjectCommand(uploadParams))
    if (data.$metadata.httpStatusCode == 200) {
        let url = `https://${uploadParams.Bucket}.s3.ap-south-1.amazonaws.com/${uploadParams.Key}`
        return url
    }
}

In SDK version 3 I dont know way to get url so I need to construct manually which does not handle encoding of url.

I found some way of encoding manually created urls but those ways are not relaible.
S3 is encoding urls with spaces and symbols to unkown format
Amazon S3 URL Encoding

I guess there should be AWS SDK way to get url the way I was getting in SDK version 2.

Alok
  • 7,734
  • 8
  • 55
  • 100
  • In what way are those resources not reliable for encoding the object key? – jarmod Aug 29 '22 at 14:39
  • @jarmod: This is not official way. We dont know how perfect this solutions are and we dont know when AWS guys change something and this will start breaking. I am looking for some official way. – Alok Aug 29 '22 at 15:14
  • If you can't find this feature in the v3 SDK then it may not exist. This wasn't available in most SDKs afaik going back a couple of years. One thing you could do, I suspect, is to [create a pre-signed URL](https://aws.amazon.com/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/) for the object and then simply split that on `?` and use the first part of the pre-signed URL which will be encoded. – jarmod Aug 29 '22 at 16:10

1 Answers1

2

here is an example how I encode the url in Nestjs Framework, you can use the same javascript function 'encodeURIComponent' in your code:

...    
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { v4 as uuidv4 } from 'uuid';
...
  private s3Client: S3Client;

  constructor(
    private readonly configService: ConfigService
  ) {
    this.s3Client = new S3Client({
      region: configService.get<string>('AWS_REGION'),
      credentials:{
        accessKeyId: configService.get<string>('AWS_ACCESS_KEY_ID'),
        secretAccessKey: configService.get<string>('AWS_SECRET_ACCESS_KEY'),
      }
    });
  }
...
  async upload(dataBuffer: Buffer, originalname: string): Promise<FileUploadResponse> {
    const fileName = `${uuidv4()}-${originalname}`;
    const encodeFileName = encodeURIComponent(fileName);
    const bucketName = this.configService.get<string>('AWS_BUCKET_NAME');
    const command: PutObjectCommand = new PutObjectCommand({
      Bucket: bucketName,
      Key: fileName,
      Body: dataBuffer
    });

    const uploadResult = await this.s3Client.send(command);

    return `https://${bucketName}.s3.amazonaws.com/${encodeFileName}`;
  }
...
}