Topic: C# Amazon S3 S.O.S.

Just downloaded the latest PLUpload.

The goal is to perform direct to S3 uploads but the sample offered is in PHP.

I am an asp.net C# developer and though I'm ashamed to admit it I cannot figure out the translation.

If anybody can create a sample I would be most grateful.

Cary Abramoff

Re: C# Amazon S3 S.O.S.

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... sad(

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

Re: C# Amazon S3 S.O.S.

PS- If you get this working for me you now have a working C# template for all your asp.net friends in the multiverse: FREE OF CHARGE smile)

Thanks again sir!

Cary

Re: C# Amazon S3 S.O.S.

PPS- I noticed my policy C# method was using a success_action 200 instead of 201. I changed it to 201 but still had the same problem. Thanks!

Re: C# Amazon S3 S.O.S.

Also getting Error: IO error. Error #2038 from control's UI Interface.

Finally I took another look at my policy versus the S3.php.

I modified as:

string policy = string.Format(@"
            {{ 'expiration': '{0}.000Z',
                'conditions': [
                {{ 'bucket': '{1}' }},                   
                {{ 'acl': '{2}' }},
                [ 'starts-with', '$key', '' ], 
                [ 'starts-with', '$Content-Type', '' ],
                {{ 'success_action_status': '201' }},
                [ 'starts-with', '$name', '' ],
                [ 'starts-with', '$Filename', '' ],
            ]
            }}", expirationDate.ToString("s"), bucket, acl);


In my debugger pre-signing it is:

"\r\n            { 'expiration': '2011-04-06T23:26:50.000Z',\r\n                'conditions': [\r\n                { 'bucket': 'multitask123' },                    \r\n                { 'acl': 'private' },\r\n                [ 'starts-with', '$key', '' ],  \r\n                [ 'starts-with', '$Content-Type', '' ],\r\n                { 'success_action_status': '201' },\r\n                [ 'starts-with', '$name', '' ],\r\n                [ 'starts-with', '$Filename', '' ],\r\n            ]\r\n            }"

Re: C# Amazon S3 S.O.S.

@caryabramoff and it still doesn't work after your last change?

If you want to see your issue fixed, do not report it here, do it on - GitHub.

Re: C# Amazon S3 S.O.S.

No sir. I am awaiting Amazon to get back to me but I am fairly sure that the policy is not being accepted. When I tested with public write on bucket I could upload, when I rely on the proper secure policy I receive the cryptic 403.

Because there is no validator, and your example is in php, even though it appears straightforward, and I can not see the issue, and there are no C# developers anywhere I could google have tried this before me I really do know know what to do next.

Try as I might I cannot add Plupload to my toolbelt. sad(

Re: C# Amazon S3 S.O.S.

Hi,

I wanted to mention that while I am approaching this problem from the 403 error and Amazon's Policy I did get an Error #2038 from PLUpload where the error display occurs.

I found the following link and it discusses Flash issues and scripts and a couple of other non-Amazon reasons this error might occur.

Also before you might consider that I do wish to point out when my bucket is public write I can upload. Further silverlight runtime also fails with 403 but I am trying to leave no stone unturned in my quest to use your beautiful uploader.

Thanks Cary smile)

http://www.judahfrangipane.com/blog/200 … -io-error/

Re: C# Amazon S3 S.O.S.

Silverlight PLUpload Error. Coincides with Amazon 403 Access denied.

IO Error.
The remote server returned an error: NotFound.

Re: C# Amazon S3 S.O.S.

Hi!

Well I figured out a foolproof way to get the policy working and then create my own in C#.

Amazon has an online policy encryption & signing tool.

I took your php and plugged the values into their online template.

Then rather than bother with my policy creation code and signing, etc. I just stuffed the one they generated into Javascript values above the plupload jquery instance.

Works in both Silverlight & Flash.

I am including a working policy and the link. Now I just have to make sure my C# output will match what Amazon creates online. Thus this post comprises an example that future asp.net PLUploader enthusiasts can massage into their own site.

Thanks for creating such a great free upload plugin. The learning curve for those new to Amazon AWS, PLUpload is steep, at least it was for me so I hope this helps ease the curve for somebody in the future. Took me 2 months so far to work out 3 direct to S3 uploaders, (Flajaxian, Aurigma & PLUPLOAD!) They all have strengths and weaknesses but I am proud to add your uploader to our offerings.

Magic Policy created at:

http://s3.amazonaws.com/doc/s3-example- … ample.html

Policy Template:
{
  "expiration": "2012-01-01T12:00:00.000Z",
  "conditions": [
    {"bucket": "Krafty1984" },
    {"acl": "private" },
    ["starts-with", "$key", ""],
    ["starts-with", "$Content-Type", "image/"],
    ["starts-with", "$success_action_status", "201"],
    ["starts-with", "$name", ""],
    ["starts-with", "$Filename", ""],
  ]
}

Best,

Cary

Re: C# Amazon S3 S.O.S.

Oh... 1 Suggestion For Silverlight Drag & Drop. Somewhere a while ago I read you guys had trouble implementing silverlight drag/drop and gave up.

I have been using the Telerik silverlight uploader for about a year for non-S3 uploads and it can handle drag and drop in IE, Chrome, FF, Safari and Mac Safari & Firefox.

They might be able to help you.

Re: C# Amazon S3 S.O.S.

Hi,

Perhaps you can help with a new issue.
The content-type in your sample seems to specify one particular type.
For example your sample assumes images are being uploaded.
Flajaxian automatically infers this as this metadata is valuable on downloads
I do know how to override the response headers on presigned url download generation but can you comment on how I can specify it to automagically decipher the file's content type. I tried leaving the content-type out of the policy but I started getting errors again.

I will play some more but ideally I would like to fill in the content-type on the fly like we do for ${filename}

Thanks!!

Re: C# Amazon S3 S.O.S.

Actually overriding the response headers will serve my needs. You can just consider this case closed. Sorry for the novel. smile)

Re: C# Amazon S3 S.O.S.

Glad you got it working, thanks for the policy generator link. Might turn out quite handy for other users.

If you want to see your issue fixed, do not report it here, do it on - GitHub.