I am trying to upload a file to aws S3 with a nodeJS server and React client app. I am new to aws so I guess I am doing something wrong. I have created a completely private backet so that only the app can access the files. The problem is that when I want to upload a file I need to get the link myBucket.getSignedUrl () in order to upload it. When I do it and send it to the frontend, the frontend fetches the link to S3 with the file I want to upload, the problem is that it returns the following error:
Access to fetch at 'https://atlasworld-progress.s3.amazonaws.com/IMG_20210202_100322.jpg?AWSAccessKeyId=AKIAZGHWWSFL5XOWPRXJ&Content-Type=image/jpeg&Expires=1633937718&Signature=o8S8MQQ3fVdONePGOT4a5ic7CcU=' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Here is the aws configuration file:
import AWS from 'aws-sdk'
AWS.config.update({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY
})
const S3_BUCKET ='atlasworld-progress';
const REGION =process.env.AWS_REGION;
const URL_EXPIRATION_TIME = 60; // in seconds
const myBucket = new AWS.S3({
params: { Bucket: S3_BUCKET},
region: REGION,
})
export const generatePreSignedPutUrl = async (fileName, fileType) => {
const url = await myBucket.getSignedUrl('putObject', {
Key: fileName,
ContentType: fileType,
Expires: URL_EXPIRATION_TIME
});
return url;
}
In the express controller it simply returns to the client the link generated by the function generatePreSignedPutUrl(). Here is the code for the frontend function in React:
const [frontPhoto, setFrontPhoto] = useState();
const upload = async (e) => {
e.preventDefault();
await JWT.checkJWT();
const requestObject = {
fileName: frontPhoto.name,
fileType: frontPhoto.type,
token: JWT.getToken()
};
axiosReq.post(`${serverPath}/prepare_s3`, requestObject).then((res) => {
//the following fetch is the one that fails
fetch(res.data, {
method: "PUT",
body: frontPhoto,
}).then((res) => {
console.log(res);
});
});
}
If anyone knows what is happening I would appreciate your help.
I would also like to ask if S3 can only be uploaded one files at a time or different files can be uploaded in a single fetch.
Thanks!
CodePudding user response:
I think this tells it all:
Access to fetch from origin 'http://localhost:3000' has been blocked by CORS policy
you need to familiarize self with CORS. If you want this to work, then you need to enable CORS from AWS.
CodePudding user response:
It's a nginx config problem, you must increase your client_max_body_size in nginx.conf
Steps:
Connect to your Beanstalk/EC2 instance via ssh:
ssh -i <key.pem> <ec2-user>@<host>
Log in as super user:
$ sudo su
Edit nginx.conf
nano /etc/nginx/nginx.conf
Add this line inside http block
client_max_body_size 50M;
Save file
Restart nginx service
$ service nginx restart
EXAMPLE NGINX CONF FILE
# Elastic Beanstalk Nginx Configuration File
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
client_max_body_size 50M; --------- add this line
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
log_format healthd '$msec"$uri"$status"$request_time"$upstream_response_time"$http_x_forwarded_for';
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}