So I am having some trouble uploading a file directly to S3. Currently my process is to make a request to nodejs/express to get a signed URL.
app.post(\'/s3S
I have been struggling a lot with this issue and finally got it figured out! I will detail my steps, hopefully it can help some one out.
I used this module: https://github.com/asafdav/ng-s3upload
I followed the steps they listed, namely:
Add CORS Configuration:
<?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>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
Add "crossdomain.xml" to the root of your bucket making it public
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" secure="false" />
</cross-domain-policy>
Create a service that will return JSON with the following:
{
"policy":"XXX",
"signature":"YYY",
"key":"ZZZ"
}
This is the most important step: make sure you are generating the correct policy document.
Here is my code in C#
StringBuilder builder = new StringBuilder();
builder.Append("{")
.Append("\"expiration\": \"")
.Append(GetFormattedTimestamp(expireInMinutes))
.Append("\",")
.Append("\"conditions\": [")
.Append("{\"bucket\": \"")
.Append(bucketName)
.Append("\"},")
.Append("{\"acl\": \"")
.Append("public-read")
.Append("\"},")
.Append("[\"starts-with\", \"$key\", \"")
.Append(prefix)
.Append("\"],")
.Append("[\"starts-with\", \"$Content-Type\", \"\"],")
.Append("[ \"content-length-range\", 0, " + 10 * 1024 * 1024 + "]")
.Append("]}");
Encoding encoding = new UTF8Encoding();
this.policyString = Convert.ToBase64String(encoding.GetBytes(builder.ToString().ToCharArray()));
this.policySignature = SignPolicy(awsSecretKey, policyString);
This generates the following Json
{
"expiration":"2014-02-13T15:17:40.998Z",
"conditions":[
{
"bucket":"bucketusaa"
},
{
"acl":"public-read"
},
[
"starts-with",
"$key",
""
],
[
"starts-with",
"$Content-Type",
""
],
[
"content-length-range",
0,
10485760
]
]
}
This document is then base64 encoded and sent down as a string.
My issue was with my policy document. The policy document is like a set of rules you define for the session like: file names must start with something (ie. upload to a subfolder), the size must be in the range.
Use the developer tools for your browser, and take a look at the network tab, see what errors AWS are returning this really helped me, it will state things like policy errors and say what condition failed. You will generally get access denied errors and this will be based on the conditions set in the policy document or wrong keys.
One other thing some browsers have issues with localhost CORS. But using the above I was able to upload files from my local dev machine using chrome.
Origin 'localhost:3000' is not allowed by Access-Control-Allow-Origin
From your error it looks like you have not set up the CORS rules on the AWS side.
This example can maybe help: https://github.com/bookingbricks/file-upload-example Using: Node, aws-sdk-js, jQuery-file-upload (blueimp)
Server:
var AWS = require('aws-sdk');
AWS.config.update({accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY});
AWS.config.region = 'eu-west-1';
app.post('/s', function (req, res) {
var s3 = new AWS.S3();
var params = {Bucket: 'BUCKETNAME', Key: req.body.name, ContentType: req.body.type};
s3.getSignedUrl('putObject', params, function(err, url) {
if(err) console.log(err);
res.json({url: url});
});
});
Client:
$.ajax({
url: '/s',
type: 'POST',
data: {name: file.name, size: file.size, type:file.type},
}).success(function(res){
$.ajax({
url: res.url,
type: 'PUT',
data: file,
processData: false,
contentType: file.type,
}).success(function(res){
console.log('Done');
});