Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created July 28, 2013 23:00
Show Gist options
  • Save bennadel/6100636 to your computer and use it in GitHub Desktop.
Save bennadel/6100636 to your computer and use it in GitHub Desktop.
Uploading Files To Amazon S3 Using A Form Post And ColdFusion
<cfscript>
// When Amazon S3 redirects the FORM POST to the success URL,
// it will pass the following parameters in the URL.
// NOTE: The etag value is quoted (ie, "abc123").
param name="url.bucket" type="string";
param name="url.key" type="string";
param name="url.etag" type="string";
// ------------------------------------------------------ //
// ------------------------------------------------------ //
// Include our Amazon S3 credentials.
include "../credentials.cfm";
// Now that we have the resource and the bucket to which it was
// posted, we can construct a full URL and generate a pre-signed,
// authorized URL.
resource = ( "/" & url.bucket & url.key );
// The expiration is defined as the number of seconds since
// epoch - as such, we need to figure out what our local timezone
// epoch is.
localEpoch = dateConvert( "utc2local", "1970/01/01" );
// The resource will expire in +1 day.
expiration = dateDiff( "s", localEpoch, ( now() + 1 ) );
// Build up the content of the signature (excluding Content-MD5
// and the mime-type).
stringToSignParts = [
"GET",
"",
"",
expiration,
resource
];
stringToSign = arrayToList( stringToSignParts, chr( 10 ) );
// Generate the signature as a Base64-encoded string.
// NOTE: Hmac() function was added in ColdFusion 10.
signature = binaryEncode(
binaryDecode(
hmac( stringToSign, aws.secretKey, "HmacSHA1", "utf-8" ),
"hex"
),
"base64"
);
// Prepare the signature for use in a URL (to make sure none of
// the characters get transported improperly).
urlEncodedSignature = urlEncodedFormat( signature );
</cfscript>
<!--- Reset the output buffer and set the page encoding. --->
<cfcontent type="text/html; charset=utf-8" />
<cfoutput>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>
Your Upload To Amazon S3 Was Successful!
</title>
</head>
<body>
<h1>
Your Upload To Amazon S3 Was Successful!
</h1>
<p>
<img src="https://s3.amazonaws.com#resource#?AWSAccessKeyId=#aws.accessID#&Expires=#expiration#&Signature=#urlEncodedSignature#" />
</p>
</body>
</html>
</cfoutput>
<cfscript>
// Include our Amazon S3 credentials.
include "../credentials.cfm";
// Set up the Success url that Amazon S3 will redirect to if the
// FORM POST has been submitted successfully.
// NOTE: If the form post fails, Amazon will present an error
// message - there is not error-based redirect.
successUrl = (
"http://" & cgi.server_name &
getDirectoryFromPath( cgi.script_name ) & "success.cfm"
);
// The expiration must defined in UCT time.
expiration = dateConvert( "local2utc", dateAdd( "h", 1, now() ) );
// NOTE: When formatting the UTC time, the hours must be in 24-
// hour time; therefore, make sure to use "HH", not "hh" so that
// your policy don't expire prematurely.
policy = {
"expiration" = (
dateFormat( expiration, "yyyy-mm-dd" ) & "T" &
timeFormat( expiration, "HH:mm:ss" ) & "Z"
),
"conditions" = [
{
"bucket" = aws.bucket
},
{
"acl" = "private"
},
{
"success_action_redirect" = successUrl
},
[ "starts-with", "$key", "/form-post/" ],
[ "starts-with", "$Content-Type", "image/" ],
[ "content-length-range", 0, 10485760 ] // 10mb
]
};
// ------------------------------------------------------ //
// ------------------------------------------------------ //
// The policy will be posted along with the FORM post as a
// hidden form field. Serialize it as JavaScript Object notation.
serializedPolicy = serializeJson( policy );
// Remove up the line breaks.
serializedPolicy = reReplace( serializedPolicy, "[\r\n]+", "", "all" );
// Encode the policy as Base64 so that it doesn't mess up
// the form post data at all.
encodedPolicy = binaryEncode(
charsetDecode( serializedPolicy, "utf-8" ) ,
"base64"
);
// ------------------------------------------------------ //
// ------------------------------------------------------ //
// To make sure that no one tampers with the FORM POST, create
// hashed message authentication code of the policy content.
// NOTE: The hmac() function was added in ColdFusion 10.
hashedPolicy = hmac(
encodedPolicy,
aws.secretKey,
"HmacSHA1",
"utf-8"
);
// Encode the message authentication code in Base64.
encodedSignature = binaryEncode(
binaryDecode( hashedPolicy, "hex" ),
"base64"
);
</cfscript>
<!--- ----------------------------------------------------- --->
<!--- ----------------------------------------------------- --->
<!--- Reset the output buffer and set the page encoding. --->
<cfcontent type="text/html; charset=utf-8" />
<cfoutput>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>
Uploading Files To Amazon S3 Using A Form Post And ColdFusion
</title>
</head>
<body>
<h1>
Uploading Files To Amazon S3 Using A Form Post And ColdFusion
</h1>
<form
method="post"
action="https://#aws.bucket#.s3.amazonaws.com/"
enctype="multipart/form-data">
<input type="hidden" name="AWSAccessKeyId" value="#aws.accessID#" />
<input type="hidden" name="key" value="/form-post/${filename}" />
<input type="hidden" name="Content-Type" value="image/*" />
<input type="hidden" name="acl" value="private" />
<input type="hidden" name="success_action_redirect" value="#htmlEditFormat( successUrl )#" />
<!--- Base64-encoded policy and request signature. --->
<input type="hidden" name="policy" value="#encodedPolicy#" />
<input type="hidden" name="signature" value="#encodedSignature#" />
<p>
Select your file:
</p>
<!---
NOTE: The file upload must be the LAST field in the
form post and must be called "file".
--->
<p>
<input name="file" type="file" size="40" />
</p>
<p>
<input type="submit" value="Upload Image" />
</p>
</form>
</body>
</html>
</cfoutput>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment