Hi Davit!
Since my last attempt to perform direct to S3 uploads with PLUpload I have garnered a bit more experience with all things S3.
The past few days I have been working on using PLUpload to perform direct to S3 uploads with the Flash,Silverlight runtimes.
I believe I am almost there but unfortunately I am receiving "Access Denied" responses from Amazon S3.
I also use Flajaxian Flash direct to S3 uploader in the same site I'm developing and those requests are successful and Amazon S3 returns HTTP 204 errors.
I figured out how to translate your S3.PHP example to C# & I believe I am doing everything correctly.
To keep the issue simple I believe we should just focus on it from the flash perspective, although I do have both crossdomain.xml & clientaccesspolicy.xml properly uploaded and readable in my target bucket.
The successful flajaxian flash direct to s3 upload request from fiddler is just about identical to the PLUpload request in terms of what I would expect except the PLUpload content length is a bit smaller when I experiment with the same file for uploading.
At any rate I am going to include the PLUpload request & response from fiddler followed by the Flajaxian request & response.
I will follow that with my source code for the plupload implementation I am trying to get working.
Hopefully you can help me get over this hump as I feel I am 99.9% there except for the dreaded x-factor that is blocking me.
In the meantime I will open a support ticket with Amazon premium support to see if they can look on their side as I have the ETAG marker which should allow them to possibly comment on what the issue might be.
Thanks very much as always Davit.
Best,
Cary
PLUPLOAD
Failure with 403 access denied...
(
POST / HTTP/1.1
Accept: text/*
Content-Type: multipart/form-data; boundary=----------KM7Ij5Ij5gL6ei4gL6KM7Ef1Ef1GI3
User-Agent: Shockwave Flash
Host: multitask123.s3.amazonaws.com
Content-Length: 10986
Connection: Keep-Alive
Pragma: no-cache
RESP:
HTTP/1.1 403 Forbidden
x-amz-request-id: DAE0C93411C8F994
x-amz-id-2: 6HSY2CDY4fBDTwqLC37+900v0JxAwECn6P+lP2jCarL2uqCS4DJHgA+VEPV0W2Hm
Content-Type: application/xml
Date: Thu, 07 Apr 2011 00:21:35 GMT
Connection: close
Server: AmazonS3
Content-Length: 231
Flajaxian works:
Success!
POST / HTTP/1.1
Accept: text/*
Content-Type: multipart/form-data; boundary=----------Ij5GI3ei4KM7GI3gL6Ij5Ij5Ef1ei4
User-Agent: Shockwave Flash
Host: multitask123.s3.amazonaws.com
Content-Length: 11980
Connection: Keep-Alive
Pragma: no-cache
response
HTTP/1.1 204 No Content
x-amz-id-2: uiSijP2mCiIh00v9j4Zt1722cMNSV1tKUizoTns0IjSgEhCp7B6oKaiGQN7TWIj9
x-amz-request-id: C9A2E1087DCAD8BF
Date: Thu, 07 Apr 2011 00:17:36 GMT
ETag: "1d7d261909c9709fbf252d3ed7542503"
Location: http://multitask123.s3.amazonaws.com/17
nzamos.jpg
Server: AmazonS3
.... What follows is my source code (aspx/c#), I understand you guys are mostly not C# but it should be relatively easy to follow as I based it all on your S3.php file.
plup.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="plup.aspx.cs" Inherits="plup" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1
tional.dtd">
<html>
<head>
<title>MultiTask123 Stylin' Multi-Select Uploads</title>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css"
type="text/css" />
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
<link rel="stylesheet" href="css/jquery.ui.plupload.css" type="text/css" />
<script src="Themeswitcher.js" type="text/javascript"></script>
<script runat="server" type="text/C#">
</script>
</head>
<body id="top">
<script src="js/plupload.full.min.js" type="text/javascript"></script>
<script src="js/jquery.plupload.queue.min.js" type="text/javascript"></script>
<script src="js/jquery.ui.plupload.min.js" type="text/javascript"></script>
<script src="js/plupload.flash.min.js" type="text/javascript"></script>
<script src="js/plupload.silverlight.min.js" type="text/javascript"></script>
<h5>
Note: This is NOT a drag & drop zone. You must use the, "Add Files" button. Peace!</h5>
<script type="text/javascript">
var ruckus = $('#ruckus').val();
var spakus = $('#spakus').val();
var allstate = $('#allstate').val();
var ucicomicsclub = $('#ucicomicsclub').val();
// Convert divs to queue widgets when the DOM is ready
$(function () {
$("#uploader").plupload({
runtimes: 'flash,silverlight',
url: 'http://multitask123.s3.amazonaws.com/',
max_file_size: '100000000mb',
multipart: true,
multipart_params: {
'key': '${filename}', // use filename as a key
'Filename': '${filename}', // adding this to keep consistency across the runtimes
'acl': 'private',
'Content-Type': 'image/jpeg',
'success_action_status': '201',
'AWSAccessKeyId': spakus,
'policy': allstate,
'signature': ucicomicsclub
},
// optional, but better be specified directly
file_data_name: 'file',
// re-use widget (not related to S3, but to Plupload UI Widget)
multiple_queues: true,
// Flash settings
flash_swf_url: '../js/plupload.flash.swf',
// Silverlight settings
silverlight_xap_url: '../js/plupload.silverlight.xap'
});
});
</script>
<div id="main">
<div class="center_wrapper">
<div id="main_content">
<form runat="server">
<input type="hidden" id="ruckus" runat="server" />
<input type="hidden" id="spakus" runat="server" />
<input type="hidden" id="allstate" runat="server" />
<input type="hidden" id="ucicomicsclub" runat="server" />
<div id="uploader" style="height: 330px;">
<p>
You browser doesn't have Flash or Silverlight support.</p>
</div>
<br style="clear: both" />
<input type="submit" value="Send" />
</form>
</div>
</div>
</div>
<script type="text/javascript" src="Themeswitcher.js"></script>
<script type="text/javascript">
function isIE() {
if (navigator.appName == "Microsoft Internet Explorer") {
return true;
}
else {
return false;
}
}
if (!isIE()) {
$.fn.themeswitcher && $('<div id="switcher" style="padding-bottom:22px;background-color:transparent;"></div>').css({
position: "absolute",
right: 10,
buttonHeight: 50,
height: 250,
top: 7
}).appendTo('#main_content').themeswitcher({ cookieName: 'hero', buttonHeight: 20, width: 250, buttonPreText: 'Krafty likes: ', initialText: 'Theme Menu (Styles Galore!)' });
}
else {
//alert('Reminder to krafty: Add HTML5 Test instead of IE Test. You have item Detect HTML 5 Features in your account');
alert('Reminder to krafty: Add HTML5 Test instead of IE Test. You have item Detect HTML 5 Features in your account\n\nThis uploader is HTML5 based & not supported by Internet Explorer. Please try the Flajaxian or Aurigma uploaders.\nAlthough it will display it will not work in IE.\nIt will work in latest Chrome, Firefox & Safari.');
}
</script>
</body>
</html>
C# Code behind for policy signing
using System;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class plup : System.Web.UI.Page
{
protected string ConstructPolicy(string bucket, DateTime expirationDate, string acl, string key)
{
// See about policy construction
// http://docs.amazonwebservices.com/Amazo
ructPolicy
string policy = string.Format(@"
{{ 'expiration': '{0}.000Z',
'conditions': [
{{ 'acl': '{1}' }},
{{ 'bucket': '{2}' }},
{{ 'success_action_status': '200' }},
[ 'starts-with', '$key', '' ],
[ 'starts-with', '$Content-Type', '' ],
]
}}", expirationDate.ToString("s"), acl, bucket);
// Encode the policy using UTF-8.
byte[] pb = System.Text.Encoding.UTF8.GetBytes(policy.ToString());
// Encode those UTF-8 bytes using Base64 and return.
return Convert.ToBase64String(pb);
}
public static string CreateSignature(string UnsignedPolicy, string AWSSecretKey)
{
string retVal = string.Empty;
HMACSHA1 sigHash = new HMACSHA1(System.Text.Encoding.UTF8.GetBytes(AWSSecretKey));
byte[] bytPolicy = System.Text.Encoding.UTF8.GetBytes(UnsignedPolicy);
byte[] bytSignature = sigHash.ComputeHash(bytPolicy);
retVal = Convert.ToBase64String(bytSignature);
return retVal;
}
protected string CreateSignature2(string policy, string secretAccessKey)
{
// Sign the policy with your Secret Access Key using HMAC SHA-1.
System.Security.Cryptography.HMACSHA1 hmac = new System.Security.Cryptography.HMACSHA1();
hmac.Key = System.Text.Encoding.UTF8.GetBytes(secretAccessKey);
byte[] signb = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(policy));
// Encode the SHA-1 signature using Base64.
return Convert.ToBase64String(signb);
}
protected override void OnPreRender(EventArgs e)
{
string bucket = System.Configuration.ConfigurationSettings.AppSettings["AmazonS3_Bucket"].ToString();
string accessKeyId = System.Configuration.ConfigurationSettings.AppSettings["AmazonS3_AWSAccessKeyId"].ToString();
string secret = System.Configuration.ConfigurationSettings.AppSettings["AmazonS3_SecretAccessKey"].ToString();
string policy = ConstructPolicy(bucket, DateTime.Now.Add(new TimeSpan(0, 0, 0, 45)), "private", accessKeyId);
string signature = CreateSignature(policy, secret);
this.ruckus.Value = bucket;
this.spakus.Value = accessKeyId;
this.allstate.Value = policy;
this.ucicomicsclub.Value = signature;
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Thanks again sir! Spasiba!
Cary