Skip to content

Instantly share code, notes, and snippets.

@carsonmcdonald
Created September 2, 2012 01:59
Show Gist options
  • Select an option

  • Save carsonmcdonald/3593744 to your computer and use it in GitHub Desktop.

Select an option

Save carsonmcdonald/3593744 to your computer and use it in GitHub Desktop.

Revisions

  1. carsonmcdonald revised this gist Sep 2, 2012. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    <html>
    <head>
    <link rel="stylesheet" type="text/css" href="styles.css" />
    <script type="text/css" src="app.js"></script>
    <script type="text/javascript" src="app.js"></script>
    </head>

    <body>
    @@ -20,7 +20,7 @@
    </tr>
    </table>

    <script>
    <script type="text/javascript">
    document.getElementById('files').addEventListener('change', handleFileSelect, false);
    setProgress(0, 'Waiting for upload.');
    </script>
  2. carsonmcdonald revised this gist Sep 2, 2012. 3 changed files with 27 additions and 32 deletions.
    2 changes: 1 addition & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -67,7 +67,7 @@ function uploadFile(file)

    /**
    * Use a CORS call to upload the given file to S3. Assumes the url
    * parameter has been signed and is accessable for upload.
    * parameter has been signed and is accessible for upload.
    */
    function uploadToS3(file, url)
    {
    37 changes: 6 additions & 31 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,35 +1,10 @@
    <html>
    <head>

    <style>
    #progress_bar {
    width: 200px;
    margin: 10px 0;
    padding: 3px;
    border: 1px solid #000;
    font-size: 14px;
    clear: both;
    opacity: 0;
    -moz-transition: opacity 1s linear;
    -o-transition: opacity 1s linear;
    -webkit-transition: opacity 1s linear;
    }
    #progress_bar.loading {
    opacity: 1.0;
    }
    #progress_bar .percent {
    background-color: #99ccff;
    height: auto;
    width: 0;
    }
    </style>

    <script src="app.js"></script>

    <link rel="stylesheet" type="text/css" href="styles.css" />
    <script type="text/css" src="app.js"></script>
    </head>

    <body>

    <table>
    <tr>
    <td>File selection:</td>
    @@ -44,12 +19,12 @@
    <td><span id="status"></span></td>
    </tr>
    </table>

    <script>
    document.getElementById('files').addEventListener('change', handleFileSelect, false);
    setProgress(0, 'Waiting for upload.');
    </script>

    </body>

    </html>
    20 changes: 20 additions & 0 deletions styles.css
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    #progress_bar {
    width: 200px;
    margin: 10px 0;
    padding: 3px;
    border: 1px solid #000;
    font-size: 14px;
    clear: both;
    opacity: 0;
    -moz-transition: opacity 1s linear;
    -o-transition: opacity 1s linear;
    -webkit-transition: opacity 1s linear;
    }
    #progress_bar.loading {
    opacity: 1.0;
    }
    #progress_bar .percent {
    background-color: #99ccff;
    height: auto;
    width: 0;
    }
  3. carsonmcdonald created this gist Sep 2, 2012.
    122 changes: 122 additions & 0 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,122 @@
    function createCORSRequest(method, url)
    {
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr)
    {
    xhr.open(method, url, true);
    }
    else if (typeof XDomainRequest != "undefined")
    {
    xhr = new XDomainRequest();
    xhr.open(method, url);
    }
    else
    {
    xhr = null;
    }
    return xhr;
    }

    function handleFileSelect(evt)
    {
    setProgress(0, 'Upload started.');

    var files = evt.target.files;

    var output = [];
    for (var i = 0, f; f = files[i]; i++)
    {
    uploadFile(f);
    }
    }

    /**
    * Execute the given callback with the signed response.
    */
    function executeOnSignedUrl(file, callback)
    {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'signput.php?name=' + file.name + '&type=' + file.type, true);

    // Hack to pass bytes through unprocessed.
    xhr.overrideMimeType('text/plain; charset=x-user-defined');

    xhr.onreadystatechange = function(e)
    {
    if (this.readyState == 4 && this.status == 200)
    {
    callback(decodeURIComponent(this.responseText));
    }
    else if(this.readyState == 4 && this.status != 200)
    {
    setProgress(0, 'Could not contact signing script. Status = ' + this.status);
    }
    };

    xhr.send();
    }

    function uploadFile(file)
    {
    executeOnSignedUrl(file, function(signedURL)
    {
    uploadToS3(file, signedURL);
    });
    }


    /**
    * Use a CORS call to upload the given file to S3. Assumes the url
    * parameter has been signed and is accessable for upload.
    */
    function uploadToS3(file, url)
    {
    var xhr = createCORSRequest('PUT', url);
    if (!xhr)
    {
    setProgress(0, 'CORS not supported');
    }
    else
    {
    xhr.onload = function()
    {
    if(xhr.status == 200)
    {
    setProgress(100, 'Upload completed.');
    }
    else
    {
    setProgress(0, 'Upload error: ' + xhr.status);
    }
    };

    xhr.onerror = function()
    {
    setProgress(0, 'XHR error.');
    };

    xhr.upload.onprogress = function(e)
    {
    if (e.lengthComputable)
    {
    var percentLoaded = Math.round((e.loaded / e.total) * 100);
    setProgress(percentLoaded, percentLoaded == 100 ? 'Finalizing.' : 'Uploading.');
    }
    };

    xhr.setRequestHeader('Content-Type', file.type);
    xhr.setRequestHeader('x-amz-acl', 'public-read');

    xhr.send(file);
    }
    }

    function setProgress(percent, statusLabel)
    {
    var progress = document.querySelector('.percent');
    progress.style.width = percent + '%';
    progress.textContent = percent + '%';
    document.getElementById('progress_bar').className = 'loading';

    document.getElementById('status').innerText = statusLabel;
    }
    10 changes: 10 additions & 0 deletions cors.xml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    <CORSConfiguration>
    <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Content-Type</AllowedHeader>
    <AllowedHeader>x-amz-acl</AllowedHeader>
    <AllowedHeader>origin</AllowedHeader>
    </CORSRule>
    </CORSConfiguration>
    55 changes: 55 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,55 @@
    <html>
    <head>

    <style>
    #progress_bar {
    width: 200px;
    margin: 10px 0;
    padding: 3px;
    border: 1px solid #000;
    font-size: 14px;
    clear: both;
    opacity: 0;
    -moz-transition: opacity 1s linear;
    -o-transition: opacity 1s linear;
    -webkit-transition: opacity 1s linear;
    }
    #progress_bar.loading {
    opacity: 1.0;
    }
    #progress_bar .percent {
    background-color: #99ccff;
    height: auto;
    width: 0;
    }
    </style>

    <script src="app.js"></script>

    </head>

    <body>

    <table>
    <tr>
    <td>File selection:</td>
    <td><input type="file" id="files" name="files[]" multiple /></td>
    </tr>
    <tr>
    <td>Progress:</td>
    <td><div id="progress_bar"><div class="percent">0%</div></div></td>
    </tr>
    <tr>
    <td>Status:</td>
    <td><span id="status"></span></td>
    </tr>
    </table>

    <script>
    document.getElementById('files').addEventListener('change', handleFileSelect, false);
    setProgress(0, 'Waiting for upload.');
    </script>

    </body>

    </html>
    25 changes: 25 additions & 0 deletions signput.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    <?php

    //
    // Change the following settings
    //
    $S3_KEY='S3 Key Here';
    $S3_SECRET='S3 Secret Here';
    $S3_BUCKET='/uploadtestbucket';

    $EXPIRE_TIME=(60 * 5); // 5 minutes
    $S3_URL='http://s3.amazonaws.com';

    $objectName='/' . $_GET['name'];

    $mimeType=$_GET['type'];
    $expires = time() + $EXPIRE_TIME;
    $amzHeaders= "x-amz-acl:public-read";
    $stringToSign = "PUT\n\n$mimeType\n$expires\n$amzHeaders\n$S3_BUCKET$objectName";
    $sig = urlencode(base64_encode(hash_hmac('sha1', $stringToSign, $S3_SECRET, true)));

    $url = urlencode("$S3_URL$S3_BUCKET$objectName?AWSAccessKeyId=$S3_KEY&Expires=$expires&Signature=$sig");

    echo $url;

    ?>