Reputation: 11
I am attempting to directly upload a video to s3 with my react native application through a flask server. I am following this guide from heroku.
React Native
postVideo({className, path}) {
console.log(`posting ${className} video at ${path}`);
const vidName = path.substring(path.indexOf('/video_')+1);
return fetch(SERVER+'/sign_s3?file_name='+vidName+'&file_type=video/mp4', {
method: 'GET',
})
.then((response) => {
response.json().then((responseText)=> {
this.uploadVideo({ uri: path, name: vidName, type: 'video/mp4' }, responseText.data, responseText.url);
})
})
.catch((error) => {
console.error(error);
});
}
uploadVideo(file, s3Data, url) {
let form = new FormData();
for(key in s3Data.fields) {
form.append(key, s3Data.fields[key]);
}
console.log(s3Data);
form.append('file', file);
return fetch(url, {
method: 'PUT',
body: form,
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.error(error);
});
}
Flask server (the environment variables are stored in a .env
file and loaded)
from flask import Flask, request, jsonify
import os, boto3
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
@app.route("/sign_s3")
def sign_s3():
S3_BUCKET = os.environ.get('S3_BUCKET')
file_name = request.args.get('file_name')
file_type = request.args.get('file_type')
s3 = boto3.client('s3')
presigned_post = s3.generate_presigned_post(
Bucket = S3_BUCKET,
Key = file_name,
Fields = {"acl": "public-read", "Content-Type": file_type},
Conditions = [
{"acl": "public-read"},
{"Content-Type": file_type}
],
ExpiresIn = 3600
)
return jsonify({
'data': presigned_post,
'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name)
})
if __name__ == "__main__":
app.run(host='0.0.0.0')
I set up a user with full access to s3 (it wasn't working with the root credentials as well) User Policy (full access to s3)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
The CORS has been setup as such
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Error
<Error>
<Code>
AccessDenied
</Code>
<Message>
Access Denied
</Message>
<RequestId>
3399C78F3BD59FAF
</RequestId>
<HostId>
mTgI5xc/iz1z69NRanZ3VfAizg6PPf0s2AdC3nE1nMqDfJYlo2trMMRUmCZMusY1hJ0xBIW21Aw=
</HostId>
</Error>
The upload works if I set the bucket to be publicly accessible, which makes me think there must be something wrong with the signing process (since I am also sure I am giving the user enough permissions to access the bucket?)
Upvotes: 1
Views: 1380
Reputation: 21
I also had this problem recently. For me it worked after changing both acl settings from "public-read" to "private".
Upvotes: 2