Friday, January 30, 2015

Upload file directly to amazone s3 bucket using html and javascript

My requirements is to upload the assets to s3 bucket. One approach is to upload file to my server and then to amazon s3, but my application deals in big file in that case it blocks my process which i don't want. Second approach i can upload directly to amazon s3 bucket in this case i can save my asset block.

I work on rails so code snippet reflects ruby but its an easy you can do in any language

Variables

AWS-BUCKET-NAME - name of the bucket in which you want to upload.
AWSAccessKeyId - Aws access key of your account.
PATH - where you want to upload file(its your logic to generate dynamic value, i used ruby SecureRandom.uuid).
REDIRECTPATH - where amazon sends the response with uploaded file path and bucket name.
Policy - it is base64 encoded policy i will explain later.
Signature - it is base64 encoded signature

HTML Code for form

AWS-BUCKET-NAME
.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
  PATH">
  AWSAccessKeyId">
 
  REDIRECTPATH">
  Policy
">
  Signature">
 
 

  File to upload to S3:
 
 

 

Policy - it a base64 encoded string which contain the policy. Policy just nothing but the cross verification of the form field value(other than AWSAccessKeyId, policy and signature fields). you 3 options starts_with, exact match and range

sample policy is
example(Its ruby code but you can easy understand it) :-
def generate_encoded_policy
policy_document = {expiration: "2029-01-01T00:00:00Z",
        conditions: [
        {bucket:
AWS-BUCKET-NAME},
        ["starts-with", "$key", key_base_name],
        {acl: "private"},
        {success_action_redirect:
REDIRECTPATH},
        ["starts-with", "$Content-Type", "application/pdf"],
        ["content-length-range", 0, 104857600]
    ]
    }.to_json

    Base64.encode64(policy_document).gsub("\n","")

end 

it is a ruby function which return me the BASE64 encoded string

Signature - It is also the base64 encoded signature
example:-
def generate_signature
       Base64.encode64(
        OpenSSL::HMAC.digest(
            OpenSSL::Digest::Digest.new('sha1'),
            AWSSECRETKEY, generate_encoded_policy)
    ).gsub("\n","")
  end


for more detail refer http://aws.amazon.com/articles/1434