Creating a Presigned S3 URL for Uploading using AWS-SDK v3 for JS and TS
In this guide, we will demonstrate how to generate a presigned S3 URL for uploading files in Amazon S3 using the AWS SDK v3 for JavaScript and TypeScript. Presigned URLs provide secure file upload/download to your S3 bucket without giving your IAM user credentials.
Code
Below is the example code in TypeScript that generates a presigned URL for S3:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; const s3Client = new S3Client({ region: 'us-west-2' }); async function generateUploadUrl() { const command = new PutObjectCommand({ Bucket: 'my-s3-bucket', Key: 'my-object-key' }); const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600 }); console.log(`Signed URL: ${signedUrl}`); }
Detailed Code Explanation
In the above code:
- We import the required
S3ClientandPutObjectCommandclasses from the@aws-sdk/client-s3package and thegetSignedUrlfunction from the@aws-sdk/s3-request-presignerpackage. - We instantiate an
S3Clientobject with the requiredregion. - We define an async function
generateUploadUrl, which will create a presigned URL. - Inside this function, we create a
PutObjectCommandobject containing theBucketandKey, which respectively specify the bucket name and object key in S3 where the uploaded file will be saved. - Then, we call
getSignedUrl, passing in ours3Client, thePutObjectCommandobject, and an options object specifying the URL's expiry time.getSignedUrlreturns a Promise which when resolved, gives us the presigned URL. - Finally, the signed URL is logged to the console.
Expected Output
The expected output from the generateUploadUrl method is a single presigned URL string:
"Signed URL: https://my-s3-bucket.s3.us-west-2.amazonaws.com/my-object-key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20220101T000000Z&X-Amz-Expires=3600&X-Amz-Signature=abcd1234&X-Amz-SignedHeaders=host"
Considerations and Caveats
- The S3 bucket and object key we use in the
PutObjectCommandconstructor have to already exist before running this code. Otherwise, the signed URL will not work. - When generating the URL, ensure your bucket allows public PUT operations to the object key you specified. You might need to adjust the bucket policy or the IAM permissions, which we'll explain in the next section.
- The supplied
expiresInvalue is in seconds. In this example, the URL will be valid for an hour (3600 seconds).
Required IAM permissions and example policy
The IAM role used by the SDK requires the s3:PutObject permission for the specified bucket and object.
Here is an example IAM policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject" ], "Resource": "arn:aws:s3:::my-s3-bucket/my-object-key" } ] }
FAQ
Q: Can I use the presigned URL for other operations besides PutObject?
A: Yes, you can replace PutObjectCommand with other commands such as GetObjectCommand, DeleteObjectCommand, etc., to create presigned URLs for download or delete operations.
Q: What happens if getSignedUrl is called with an expired time?
A: An expired time in the past will result in a presigned URL that's not valid. The expiresIn value in the options object passed to getSignedUrl must be a future time.
Q: What's the maximum expiresIn value for getSignedUrl?
A: getSignedUrl() allows for a maximum expiresIn value of 604800 seconds (one week).
Q: Why is my presigned URL not working?
A: Check if you set the file name (object key) and bucket name correctly in PutObjectCommand, and if your bucket policy or IAM permissions allow PutObject operations. Also, ensure that the URL has not expired.