Why you should use this method?
Firstly, with the presigned URL, you don't have to send your file to the backend to upload it to the S3 bucket; you can directly upload the file from your front-end application to the S3 bucket securely. It's a convenient and secure approach. This URL can be provided to your users to grant temporary access to a specific S3 object.
How to use the presigned URL
- Create an S3 bucket
Here, I am creating an S3 bucket through a CloudFormation template in YAML with minimal configuration. You can also create it from the AWS console or convert it to JSON.
resources:
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: My-S3-Bucket-Name
VersioningConfiguration:
Status: Enabled
CorsConfiguration:
CorsRules:
- AllowedMethods:
- GET
- PUT
- POST
- HEAD
AllowedOrigins:
- "*"
AllowedHeaders:
- "*"
MyS3BucketPolicy:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref MyS3Bucket
PolicyDocument:
Statement:
- Action:
- 's3:GetObject'
Effect: Allow
Resource: !Join
- ''
- - 'arn:aws:s3:::'
- !Ref MyS3Bucket
- /*
Sid: "PublicReadGetObject"
Principal: '*'
- Make a Lambda function to get a signed URL
const AWS = require("aws-sdk");
const region = process.env.REGION;
AWS.config.update({ region });
const s3 = new AWS.S3();
async function getPresignedUploadUrl(event) {
const { bucket, directory, fileName } = event;
const key = `${directory}/${fileName}`;
const url = await s3.getSignedUrl("putObject", {
Bucket: bucket,
Key: key,
ContentType: "image/*",
Expires: 300
});
return url;
}
module.exports = { getPresignedUploadUrl };
- Function to get the signed URL in the frontend
const getS3Signeture = async (name) => {
// name = name of the current selected file EG: image.jpg
const result = await axios.post("ENDPOINT-OF-THE-getPresignedUploadUrl-LAMBDA", {
bucket: "My-S3-Bucket-Name",
directory: "FOLDER-NAME",
fileName: Date.now() + name,
});
return result.data;
};
export default getS3Signeture;
- Function to upload the file to S3 with the presigned URL
const s3UploadImage = async (presignedUploadUrl, file) => {
const response = await fetch(
new Request(presignedUploadUrl, {
method: "PUT",
body: file,
headers: new Headers({
"Content-Type": "image/*",
ACL: "public-read",
}),
})
);
if (response.status === 200) {
const data = {
url: response.url.split("?")[0],
status: 200,
};
return data;
} else {
const failed = {
url: "",
status: 500,
};
return failed;
}
};
export default s3UploadImage;
Please note that you may need to adapt the code to your specific use case and environment. Additionally, ensure you have the necessary dependencies such as Axios for making HTTP requests.
Top comments (0)