Created
September 2, 2012 01:59
-
-
Save carsonmcdonald/3593744 to your computer and use it in GitHub Desktop.
Use S3 CORS FileAPI uploader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 accessible 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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<CORSConfiguration> | |
<CORSRule> | |
<AllowedOrigin>*</AllowedOrigin> | |
<AllowedMethod>PUT</AllowedMethod> | |
<MaxAgeSeconds>3000</MaxAgeSeconds> | |
<AllowedHeader>Content-Type</AllowedHeader> | |
<AllowedHeader>x-amz-acl</AllowedHeader> | |
<AllowedHeader>origin</AllowedHeader> | |
</CORSRule> | |
</CORSConfiguration> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<link rel="stylesheet" type="text/css" href="styles.css" /> | |
<script type="text/javascript" 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 type="text/javascript"> | |
document.getElementById('files').addEventListener('change', handleFileSelect, false); | |
setProgress(0, 'Waiting for upload.'); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
?> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment