5

I just started using aws-sdk on my app to upload files to S3, and i'm debating whether to use aws-sdk v2 or v3.

V2 is the whole package, which is super bloated considering i only need the s3 services, not the myriad of other options. However, the documentation is very cryptic and im having a really hard time getting the equivalent getSignedUrl function to work in v3.

In v2, i have this code to sign the url and it works fine. I am using express on the server

import aws from 'aws-sdk';

const signS3URL = (req,res,next) => {
    const s3 = new aws.S3({region:'us-east-2'});
    const {fileName,fileType} = req.query;
    const s3Params = {
        Bucket : process.env.S3_BUCKET,
        Key : fileName,
        ContentType:fileType,
        Expires: 60,
    };

    s3.getSignedUrl('putObject',s3Params,(err,data)=>{
        if(err){
            next(err);
        }
        res.json(data);
    });
}

Now I've been reading documentation and examples trying to get the v3 equivalent to work, but i cant find any working example of how to use it. Here is how I have set it up so far

import {S3Client,PutObjectCommand} from '@aws-sdk/client-s3';
import {getSignedUrl} from '@aws-sdk/s3-request-presigner';

export const signS3URL = async(req,res,next) => {
    console.log('Sign')
    const {fileName,fileType} = req.query;
    const s3Params = {
        Bucket : process.env.S3_BUCKET,
        Key : fileName,
        ContentType:fileType,
        Expires: 60,
        // ACL: 'public-read'
    };

    const s3 = new S3Client()
    s3.config.region = 'us-east-2'
    const command = new PutObjectCommand(s3Params)
    console.log(command)


    await getSignedUrl(s3,command).then(signature =>{
        console.log(signature)
        res.json(signature)
    }).catch(e=>next(e))
}

There are some errors in this code, and the first I can identify is creating the command variable using the PutObjectCommand function provided by the SDK. The documentation does not clarify to me what i need to pass it as the "input" https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/interfaces/putobjectcommandinput.html

Does anyone with experience using aws-sdk v3 know how to do this?

Also a side-question, where can i find the api reference for v2???? cuz all i find is the sdk docs that say "v3 now available" and i cant seem to find the reference to v2....

thanks for your time

li ki
  • 342
  • 3
  • 11
xunux
  • 1,531
  • 5
  • 20
  • 33
  • I would not use both await and then. Did you try `const url = await getSignedUrl(s3, command);`? Version 2 docs [here](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/_index.html). – jarmod Apr 16 '21 at 14:57
  • why woulndt you. use await and then? in the end it's just handling the promise right? I can try `const url = await getSignedUrl...` and will let u know, but i think the issue im having is with the PutObjectCommand params – xunux Apr 16 '21 at 15:12
  • Actually it looks as if the `PutObjectCommand` is working ok, i think... i tried changing the await function to how you described it, but im getting the same error. The error is `TypeError: date.getUTCFullYear is not a function` so i must be passing a wrong parameter somewhere – xunux Apr 16 '21 at 15:18
  • 1
    See [using await and then together](https://stackoverflow.com/questions/55019621/using-async-await-and-then-together). In my opinion, it's unnecessary, it's less clear, and it can lead to confusion about which code is doing what. – jarmod Apr 16 '21 at 15:20

2 Answers2

6

The following code would give you a signedUrl in a JSON body with the key as signedUrl.

const signS3URL = async (req, res, next) => {
    const { fileName, fileType } = req.query;
    const s3Params = {
        Bucket: process.env.S3_BUCKET,
        Key: fileName,
        ContentType: fileType,
        // ACL: 'bucket-owner-full-control'
    };
    const s3 = new S3Client({ region: 'us-east-2' })
    const command = new PutObjectCommand(s3Params);

    try {
        const signedUrl = await getSignedUrl(s3, command, { expiresIn: 60 });
        console.log(signedUrl);
        res.json({ signedUrl })
    } catch (err) {
        console.error(err);
        next(err);
    }
}

Keep the ACL as bucket-owner-full-control if you want the AWS account owning the Bucket to access the files.

You can go to the API Reference for both the JS SDK versions from here

GSSwain
  • 5,787
  • 2
  • 19
  • 24
1

In reference to the AWS docs and @GSSwain's answer (cannot comment, new) this link will show multiple examples getSignedURL examples.

Below is an example of uploading copied from AWS docs

// Import the required AWS SDK clients and commands for Node.js

import {
  CreateBucketCommand,
  DeleteObjectCommand,
  PutObjectCommand,
  DeleteBucketCommand }
from "@aws-sdk/client-s3";
import { s3Client } from "./libs/s3Client.js"; // Helper function that creates an Amazon S3 service client module.
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import fetch from "node-fetch";

// Set parameters
// Create a random name for the Amazon Simple Storage Service (Amazon S3) bucket and key
export const bucketParams = {
  Bucket: `test-bucket-${Math.ceil(Math.random() * 10 ** 10)}`,
  Key: `test-object-${Math.ceil(Math.random() * 10 ** 10)}`,
  Body: "BODY"
};
export const run = async () => {
  try {
    // Create an S3 bucket.
    console.log(`Creating bucket ${bucketParams.Bucket}`);
    await s3Client.send(new CreateBucketCommand({ Bucket: bucketParams.Bucket }));
    console.log(`Waiting for "${bucketParams.Bucket}" bucket creation...`);
  } catch (err) {
    console.log("Error creating bucket", err);
  }
  try {
    // Create a command to put the object in the S3 bucket.
    const command = new PutObjectCommand(bucketParams);
    // Create the presigned URL.
    const signedUrl = await getSignedUrl(s3Client, command, {
      expiresIn: 3600,
    });
    console.log(
      `\nPutting "${bucketParams.Key}" using signedUrl with body "${bucketParams.Body}" in v3`
    );
    console.log(signedUrl);
    const response = await fetch(signedUrl, {method: 'PUT', body: bucketParams.Body});
    console.log(
      `\nResponse returned by signed URL: ${await response.text()}\n`
    );
  } catch (err) {
    console.log("Error creating presigned URL", err);
  }

  try {
    // Delete the object.
    console.log(`\nDeleting object "${bucketParams.Key}"} from bucket`);
    await s3Client.send(
      new DeleteObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key })
    );
  } catch (err) {
    console.log("Error deleting object", err);
  }
  try {
    // Delete the S3 bucket.
    console.log(`\nDeleting bucket ${bucketParams.Bucket}`);
    await s3Client.send(
      new DeleteBucketCommand({ Bucket: bucketParams.Bucket })
    );
  } catch (err) {
    console.log("Error deleting bucket", err);
  }
};
run();
RJA
  • 129
  • 1
  • 7