Uploading Image to Amazon s3 with HTML, javascript & jQuery with Ajax Request (No PHP)

Solution 1:

Got Amazon S3 & CORS working on js and html5 using XMLHTTPObject based on this article article.

1: CORS only works from a proper URL "http://localhost". (file///xyz will make you go insane)

2 : Make sure you got the POLICY and Secret compiled correctly - here is my policy and this is the link you can get the project to get you started with Signature and Policy -- do not publish this JS with your Secret EVER!

POLICY_JSON = { "expiration": "2020-12-01T12:00:00.000Z",
            "conditions": [
            {"bucket": this.get('bucket')},
            ["starts-with", "$key", ""],
            {"acl": this.get('acl')},                           
            ["starts-with", "$Content-Type", ""],
            ["content-length-range", 0, 524288000]
            ]
          };


    var secret = this.get('AWSSecretKeyId');
    var policyBase64 = Base64.encode(JSON.stringify(POLICY_JSON));
    console.log ( policyBase64 )

    var signature = b64_hmac_sha1(secret, policyBase64);
    b64_hmac_sha1(secret, policyBase64);
    console.log( signature);

Here is the JS code

function uploadFile() {

    var file = document.getElementById('file').files[0];
    var fd = new FormData();

    var key = "events/" + (new Date).getTime() + '-' + file.name;

    fd.append('key', key);
    fd.append('acl', 'public-read'); 
    fd.append('Content-Type', file.type);      
    fd.append('AWSAccessKeyId', 'YOUR ACCESS KEY');
    fd.append('policy', 'YOUR POLICY')
    fd.append('signature','YOUR SIGNATURE');

    fd.append("file",file);

    var xhr = new XMLHttpRequest();

    xhr.upload.addEventListener("progress", uploadProgress, false);
    xhr.addEventListener("load", uploadComplete, false);
    xhr.addEventListener("error", uploadFailed, false);
    xhr.addEventListener("abort", uploadCanceled, false);

    xhr.open('POST', 'https://<yourbucket>.s3.amazonaws.com/', true); //MUST BE LAST LINE BEFORE YOU SEND 

    xhr.send(fd);
  }

Helper functions

function uploadProgress(evt) {
    if (evt.lengthComputable) {
      var percentComplete = Math.round(evt.loaded * 100 / evt.total);
      document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
    }
    else {
      document.getElementById('progressNumber').innerHTML = 'unable to compute';
    }
  }

  function uploadComplete(evt) {
    /* This event is raised when the server send back a response */
    alert("Done - " + evt.target.responseText );
  }

  function uploadFailed(evt) {
    alert("There was an error attempting to upload the file." + evt);
  }

  function uploadCanceled(evt) {
    alert("The upload has been canceled by the user or the browser dropped the connection.");
  }

Then the HTML Form

 <form id="form1" enctype="multipart/form-data" method="post">
<div class="row">
  <label for="file">Select a File to Upload</label><br />
  <input type="file" name="file" id="file" onchange="fileSelected()"/>
</div>
<div id="fileName"></div>
<div id="fileSize"></div>
<div id="fileType"></div>
<div class="row">
  <input type="button" onclick="uploadFile()" value="Upload" />
</div>
<div id="progressNumber"></div>

Happy CORS-ing!

Solution 2:

Amazon just allowed Cross-Origin Resource Sharing, in theory it allows your users to upload to S3 directly, without using your server (and PHP) as a proxy.

Heres the docs -> http://docs.amazonwebservices.com/AmazonS3/latest/dev/cors.html

They do a great job of telling you how to enable it on an S3 bucket, but iv found no actual javascript examples of how to get data from client to bucket.

First person to post CORS.js is a legend xD