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
S3Client
andPutObjectCommand
classes from the@aws-sdk/client-s3
package and thegetSignedUrl
function from the@aws-sdk/s3-request-presigner
package. - We instantiate an
S3Client
object with the requiredregion
. - We define an async function
generateUploadUrl
, which will create a presigned URL. - Inside this function, we create a
PutObjectCommand
object containing theBucket
andKey
, 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
, thePutObjectCommand
object, and an options object specifying the URL's expiry time.getSignedUrl
returns 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
PutObjectCommand
constructor 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
expiresIn
value 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.