Skip to content

Instantly share code, notes, and snippets.

@bathtimefish
Last active December 23, 2015 15:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bathtimefish/6657812 to your computer and use it in GitHub Desktop.
Save bathtimefish/6657812 to your computer and use it in GitHub Desktop.
Direct Browser Uploading to Amazon S3 cf. http://goo.gl/PAB5Ou
//wrote for AMD
define([], function () {
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();
var url = 's3url.php?name=' + file.name + '&type=' + file.type;
xhr.open('GET', url, 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(e) {
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)
{
//console.log("setProgress=" + percent);
var progress = document.querySelector('.percent');
progress.style.width = percent + '%';
progress.textContent = percent + '%';
document.getElementById('progress_bar').className = 'loading';
document.getElementById('status').innerText = statusLabel;
}
window.onload = function() {
document.getElementById('files').addEventListener('change', handleFileSelect, false);
setProgress(0, 'Waiting for upload.');
}
});
<!doctype html><!-- Yeoman generator-webapp -->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>AWS S3 Direct Upload Tests</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<!-- build:css(.tmp) styles/main.css -->
<link rel="stylesheet" href="styles/main.css">
<!-- endbuild -->
</head>
<body>
<!--[if lt IE 10]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<div class="container">
<div class="header">
<ul class="nav nav-pills pull-right">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
<h3 class="text-muted">AWS S3 Direct Upload Test</h3>
</div>
<div >
<div>
<h3>File selection:</h3>
<input type="file" id="files" name="files[]" multiple />
</div>
<div>
<h3>Progress:</h3>
<div id="progress_bar"><div class="percent">0%</div></div>
<div><span id="status"></span></div>
</div>
</div>
<div class="footer">
<p>♥ from the Yeoman team</p>
</div>
</div>
<!-- build:js scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/jquery.js"></script>
<!-- endbower -->
<!-- endbuild -->
<!-- build:js scripts/main.js -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
<!-- endbuild -->
</body>
</html>
#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;
}
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://www.example.com</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>x-amz-acl</AllowedHeader>
<AllowedHeader>origin</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
<?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;
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment