Disclaimer - When uploading files to s3 directly from front end, your AWS credentials are exposed in the network tab. Refrain from uploading files to protected S3 buckets directly from FE. Always use a server to upload files.
You need to install aws-sdk
npm package in order to upload files to s3 buckets.
npm install aws-sdk --save
Make sure the bucket has following policy
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<ExposeHeader>ETag</ExposeHeader>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
The ETag header must be exposed or bigger uploads will not complete.
Let's write some React
import AWS from 'aws-sdk'
in the component constructor set the AWS access key and the secret keys. You get them straight from the aws console.
AWS.config.update({
accessKeyId: AWSAccessKeyId,
secretAccessKey: AWSSecretKey
})
Create the bucket in the constructor as well
Always double check bucket's name and region.
this.myBucket = new AWS.S3({
params: { Bucket: 'video-bucket-xyz'},
region: 'ap-south-1',
})
Now when ever you want to upload a file to the bucket call the following function and pass the selected file as function argument.
uploadFile = (file) => {
const params = {
ACL: 'public-read',
Key: file.name,
ContentType: file.type,
Body: file,
}
this.myBucket.putObject(params)
.on('httpUploadProgress', (evt) => {
// that's how you can keep track of your upload progress
this.setState({
progress: Math.round((evt.loaded / evt.total) * 100),
})
})
.send((err) => {
if (err) {
// handle the error here
}
})
}
you can read more about putObject here.
References
aws-sdk
Top comments (14)
This is so helpful thank you! One question I have is if you wanted to ensure that the files go into a sub-folder within your bucket, do you know how best to go about this? I've tried entering some further params into the myBucket variable but have been unsuccessful.
Many thanks!
When you want the files to go to a subfolder, You should add the location before the file name in the key and separate each sub-folder by a forward slash '/'.
For example: if I want to save to the 'profiles' folder inside 'images' in my bucket,
My key is going to be: images/profiles/file.name
And yeah do this on the backend to avoid exposing your keys.
Amazing, I managed to figure this out in the end. Thanks for your help too! :)
Your secret key is publicly available, isn't it?
Is it really a good practice to leave the Access and Secret Keys public on the front-end?
I think it's not a good practice.
Then you should probably put a disclaimer at the beginning.
ohh, yeah sorry, I forgot. Thank you for pointing out 😊.
I agree with you
To upload large files (1-10GB) from react into s3, can we automatically break the file into pieces, send and reassemble into one file? With same API?
hey, when you do putObject it already breaks the file into pieces, you need not to worry.
You also forgot to add syntax highlighting to your code blocks many people miss that on here 😄
Hey thank you, didn't know about that 😊.
Please how can i get the url of the uploaded file?