Web App Development

Uploading a file to S3 on the client

For the upload a form is posted to amazonaws.com. I'll use Python and Django templates for it.

The form template

    <title>S3 POST Form</title> 
    <form action="https://.s3.amazonaws.com/" enctype="multipart/form-data" method="post">
		<input name="key" type="hidden" value="uploads/${filename}" />
	      <input name="AWSAccessKeyId" type="hidden" value="" /> 
	      <input name="acl" type="hidden" value="public-read" /> 
	      <input name="success_action_redirect" type="hidden" value="http://example.com" />
	      <input name="policy" type="hidden" value="" />
	      <input name="signature" type="hidden" value="" />

      	File to upload to S3: 
      	<input name="file" type="file" /> 
		<input type="submit" value="Upload File to S3" /> 

The python code

from django.http import HttpResponse
from django.template import loader, Context
import base64
import hmac, sha

def upload(request):
t = loader.get_template("upload.html")
vars = {}

policy = base64.b64encode(policy_json)
aws_secret_key = "SEE BELOW"
signature = base64.b64encode(hmac.new(aws_secret_key, policy, sha).digest())

vars["signature"] = signature
vars["policy"] = policy
vars["aws_access_key"] = "SEE BELOW"
vars["bucket"] = "your-bucket"

return HttpResponse(t.render(Context(vars)))

policy_json = """
{"expiration": "2013-01-01T00:00:00Z",
"conditions": [
{"bucket": "your-bucket"},
["starts-with", "$key", "uploads/"],
{"acl": "public-read"},
{"success_action_redirect": "http://example.com"},
["content-length-range", 0, 1048576]
Below: You can find your keys at https://aws-portal.amazon.com/gp/aws/securityCredentials. The aws access key is public and will be sent to the client. The secret access key is used to calculate a signuature for the policy json.
Make sure to replace "your-bucket" with the name of your bucket. It should work now.

A problem I ran into

Initially I got this error:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
That was because I had the json in my policy field, but actually it should contain the base64-encoded json.


Follow me on Twitter