Uploading Files to S3 with Plupload and ASP.NET

Plupload is a component that makes it easy to upload files through a web browser. When you add Plupload  to a web page, users can select multiple files to upload and users can see the progress while an upload is taking place. To read more about Plupload see http://www.plupload.com/.

Plupload can be configured to upload files to Amazon S3. The following article describes how to create an ASP.NET web page which uploads files to S3 using Plupload.

Start by download the sample .NET web project at the bottom of this article. The project contains a file called crossdomain.xml which must be uploaded to the root of your S3 bucket. The crossdomain.xml file contains the following lines of code:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "<a href="http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd</a>">
<cross-domain-policy>
<allow-access-from domain="*" secure="false" />
</cross-domain-policy>

Make sure the crossdomain.xml file has public permission on S3 after you upload it. The crossdomain.xml file will allow Flash, which Plupload uses, to interact with your bucket.

The sample project contains the Plupload files and an ASP.NET page which hosts Plupload. The ASP.NET web page is displayed below.

<%@ Page Language="C#"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

//You must upload the crossdomain.xml file in this project to the root of your bucket in
//order for this example to work. You must make this file public (everyone view permission).

String AWSAccessKeyID;
String AWSSecretAccessKey;
String BucketName;
String PolicyDocument;
String PolicyDocumentSignature;

protected void Page_Load(object sender, EventArgs e)
{
AWSAccessKeyID = "";        //** put your value here **
AWSSecretAccessKey = "";    //** put your value here **
BucketName = "";            //** put your value here **

DateTime ExpirationDate;
ExpirationDate = DateTime.UtcNow.AddMinutes(60);

PolicyDocument = "";
PolicyDocument += "{";
PolicyDocument += "  \"expiration\": \"" + ExpirationDate.ToString("s") + ".000Z\",";
PolicyDocument += "  \"conditions\": [";
PolicyDocument += "    {\"bucket\": \"" + BucketName + "\"},";
PolicyDocument += "    {\"acl\": \"public-read\"},";
PolicyDocument += "    {\"success_action_status\": \"201\"},";
//PolicyDocument += "    [\"starts-with\", \"$Content-Type\", \"image/\"],";
PolicyDocument += "    [\"starts-with\", \"$Filename\", \"\"],";
PolicyDocument += "    [\"starts-with\", \"$name\", \"\"],";
PolicyDocument += "    [\"starts-with\", \"$key\", \"\"],";
PolicyDocument += "  ]";
PolicyDocument += "}";

Byte[] ByteArray;
ByteArray = System.Text.Encoding.UTF8.GetBytes(PolicyDocument);
PolicyDocument = System.Convert.ToBase64String(ByteArray);

ByteArray = System.Text.Encoding.UTF8.GetBytes(AWSSecretAccessKey);
System.Security.Cryptography.HMACSHA1 MyHMACSHA1 = new System.Security.Cryptography.HMACSHA1(ByteArray);

ByteArray = System.Text.Encoding.UTF8.GetBytes(PolicyDocument);
Byte[] HashArray;

HashArray = MyHMACSHA1.ComputeHash(ByteArray);
PolicyDocumentSignature = System.Convert.ToBase64String(HashArray);
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Plupload to Amazon S3 Example</title>
<style type="text/css">
body {
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
color:#333;
}
</style>

<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/themes/base/jquery-ui.css" type="text/css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript"></script>
<script src=" https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="/plupload_v1.5.4/js/jquery.ui.plupload/css/jquery.ui.plupload.css" type="text/css" />
<script type="text/javascript" src="/plupload_v1.5.4/js/plupload.js"></script>
<script type="text/javascript" src="/plupload_v1.5.4/js/plupload.gears.js"></script>
<script type="text/javascript" src="/plupload_v1.5.4/js/plupload.silverlight.js"></script>
<script type="text/javascript" src="/plupload_v1.5.4/js/plupload.flash.js"></script>
<script type="text/javascript" src="/plupload_v1.5.4/js/plupload.browserplus.js"></script>
<script type="text/javascript" src="/plupload_v1.5.4/js/plupload.html4.js"></script>
<script type="text/javascript" src="/plupload_v1.5.4/js//plupload.html5.js"></script>
<script type="text/javascript" src="/plupload_v1.5.4/js/jquery.ui.plupload/jquery.ui.plupload.js"></script>
</head>
<body>

<h1>Plupload to Amazon S3 Example</h1>
<div id="uploader">
<p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>
</div>

<script type="text/javascript">
// Convert divs to queue widgets when the DOM is ready
$(function () {
$("#uploader").plupload({
runtimes: 'flash,silverlight',
url: 'https://<%=BucketName%>.s3.amazonaws.com/',
max_file_size: '50mb',
multipart: true,
multipart_params: {
'key': '${filename}', // use filename as a key
'Filename': '${filename}', // adding this to keep consistency across the runtimes
'acl': 'public-read',
//'Content-Type': 'image/jpeg',
'success_action_status': '201',
'AWSAccessKeyId': '<%=AWSAccessKeyID%>',
'policy': '<%=PolicyDocument%>',
'signature': '<%=PolicyDocumentSignature%>'
},

// !!!Important!!!
// this is not recommended with S3, since it will force Flash runtime into the mode, with no progress indication
//resize : {width : 800, height : 600, quality : 60},  // Resize images on clientside, if possible
// 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,

// Specify what files to browse for
//filters : [
//                {title : "JPEG files", extensions : "jpg"}
//],

// Flash settings
flash_swf_url: '/plupload_v1.5.4/js/plupload.flash.swf',

// Silverlight settings
silverlight_xap_url: '/plupload_v1.5.4/js/plupload.silverlight.xap'
});
});
</script>
</body>
</html>

When using the code enter your values for AWSAccessKeyID, AWSSecretAccessKey, and BucketName.

The code starts by creating a policy document. The policy document describes what is allowed to be uploaded. Read more about policy documents at http://docs.amazonwebservices.com/AmazonS3/latest/dev/HTTPPOSTForms.html.

Next the code creates a hash of the policy document using your AWSSecretAccessKey. Both the hash and the policy document are uploaded to Amazon. Amazon knows the policy document is from you since only you can create the correct hash.

Next the code sets references to the required jQuery and Plupload files.

Next the code created an instance of Plupload and sets it’s parameters. Here we use the values of the BucketName, AWSAccessKeyID, policy document, and policy document hash.

When the code is run the Plupload window is displayed and the user can select files to upload. When the start upload button is clicked, the files will be uploaded to the bucket specified in  the code.

Download the Plupload sampe project (259 KB)