Trying to upload to s3 getting OPTIONS 403 and No 'Access-Control-Allow-Origin' header is present.

815 views
Skip to first unread message

Rickard Liljeberg

unread,
May 7, 2014, 5:08:24 PM5/7/14
to jquery-f...@googlegroups.com
I am trying to upload straight to amazon s3.

Here is my code
 form.fileupload({
 url
: form.attr('action'),
 type
: 'POST',
 datatype
: 'xml',
 add
: function (event, data) {


 
// Message on unLoad.
 window
.onbeforeunload = function () {
 
return '[[[You have unsaved changes.]]]';
 
};


 
// Submit
 data
.submit();
 
},
...

The form looks like this
<form action="//s3-eu-west-1.s3.amazonaws.com/laurassuperbucket/" method="POST" enctype="multipart/form-data"class="UploadForm">

 
<input type="hidden" name="key" value="${filename}">
 
<input type="hidden" name="AWSAccessKeyId" value="@Model[0]">
 
<input type="hidden" name="acl" value="private">
 
<input type="hidden" name="success_action_status" value="201">
 
<input type="hidden" name="policy" value="@Model[1]">
 
<input type="hidden" name="signature" value="@Model[2]">


 
<input type="file" name="file" />

 
<div class="progress"><div class="bar"></div></div>
</form>

My CORS for the bucket looks like this
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   
<CORSRule>
       
<AllowedOrigin>*</AllowedOrigin>
       
<AllowedMethod>PUT</AllowedMethod>
       
<AllowedMethod>POST</AllowedMethod>
       
<AllowedMethod>DELETE</AllowedMethod>
       
<MaxAgeSeconds>3000</MaxAgeSeconds>
       
<AllowedHeader>*</AllowedHeader>
   
</CORSRule>
</CORSConfiguration>


No matter what I get this in my chrome console
XMLHttpRequest cannot load http://s3-eu-west-1.s3.amazonaws.com/laurassuperbucket/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

If I look under network in chrome it says Method OPTIONS, Status text 403 Forbidden

so it seems to be an OPTIONS problem but I don't know how to solve it.

Rickard Liljeberg

unread,
May 21, 2014, 5:11:01 AM5/21/14
to jquery-f...@googlegroups.com
Not sure what was actually wrong because I changed a lot. I am not using aws sign4 but rather the previous one.
and now it works with the following code:

<form action="//@(Model[5]).s3.amazonaws.com/" method="POST" enctype="multipart/form-data" class="UploadForm">
<input type="hidden" name="acl" value="private">
<input type="hidden" name="awsaccesskeyid" value="@Model[0]">
<input type="hidden" name="key" value="${filename}">
<input type="hidden" name="policy" value="@Model[1]">
<input type="hidden" name="success_action_status" value="201">
<input type="hidden" name="signature" value="@Model[2]">
<!--
<input type="hidden" name="x-amz-algorithm" value="AWS4-HMAC-SHA256" />
<input type="hidden" name="x-amz-credential" value="@Model[4]" />
<input type="hidden" name="x-amz-date" value="@Model[3]" />
<input type="hidden" name="x-amz-signature" value="@Model[2]">
-->
<input type="file" name="file" />

<!-- Progress Bar to show upload completion percentage -->
<div class="progress"><div class="bar"></div></div>


<input type="submit" />
</form>

<!-- Used to Track Upload within our App -->
<form action="process-form-data.php" method="POST">
<input type="hidden" name="upload_original_name" />

<label for="upload_custom_name">Name:</label><br />
<input type="text" name="upload_custom_name" id="upload_custom_name" /><br />

<input type="submit" value="Save" />
</form>

@section scripts
{
    <script>
$(function () {
$('.UploadForm').each(function () {
var form = $(this);

form.fileupload({
url: form.attr('action'),
type: 'POST',
datatype: 'xml',
add: function (event, data) {

// Message on unLoad.
window.onbeforeunload = function () {
return '[[[You have unsaved changes.]]]';
};

// Submit
data.submit();
},
send: function (e, data) {
// onSend
},
progress: function (e, data) {
// This is what makes everything really cool, thanks to that callback
// you can now update the progress bar based on the upload progress.
var percent = Math.round((data.loaded / data.total) * 100);
$('.bar').css('width', percent + '%');
},
fail: function (e, data) {
// Remove 'unsaved changes' message.
window.onbeforeunload = null;
},
success: function (data) {
// onSuccess
},
done: function (event, data) {
// Fill the name field with the file's name.
$('#upload_original_name').val(data.originalFiles[0].name);
$('#upload_custom_name').val(data.originalFiles[0].name);
},
});
});
});
    </script>
}



And my .net mvc controller looks like this

string signDate = DateTime.UtcNow.ToString("yyyyMMdd");
string dateNow = signDate + "T000000Z";

   string credential = accesskey + "/" + signDate + "/eu-west-1/s3/aws4_request";

var policy = @"{
'expiration': '" + DateTime.UtcNow.AddHours(3).ToString("o") + @"',
'conditions': 
[
{
'acl': 'private'
},
{
'bucket': '" + bucket + @"'
},
[
'starts-with',
'$key',
''
],
{
'success_action_status': '201'
}
]
}";


/*  used for version 4 of aws
{
'x-amz-algorithm': 'AWS4-HMAC-SHA256'
},
{
'x-amz-credential': '" + credential + @"'
},
{
'x-amz-date': '" + dateNow + @"'
}
*/

   policy = policy.Replace("'", "\"");

var myCredentials = new BasicAWSCredentials(accesskey, secret);
   var signedPolicy = S3PostUploadSignedPolicy.GetSignedPolicy(policy, myCredentials);


List<string> model = new List<string>();
model.Add(accesskey); //not used
model.Add(signedPolicy.Policy);
model.Add(signedPolicy.Signature);
model.Add(dateNow);
model.Add(credential);
model.Add(bucket);
model.Add(policy);

return View("aws", "_Admin", model);


Zeovaldo Rocha

unread,
May 21, 2014, 10:53:03 AM5/21/14
to jquery-f...@googlegroups.com
insert from options:

      xhrFields: {
         withCredentials: true
Reply all
Reply to author
Forward
0 new messages