Skip to content

Instantly share code, notes, and snippets.

@stomita
Created December 25, 2013 07:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stomita/8121197 to your computer and use it in GitHub Desktop.
Save stomita/8121197 to your computer and use it in GitHub Desktop.
S3 File List Visualforce page final.
<apex:page showHeader="false"
standardStylesheets="false"
sidebar="false"
contentType="text/html"
applyBodyTag="false"
applyHtmlTag="false"
cache="true"
docType="html-5.0">
<html>
<head>
<script src="//sdk.amazonaws.com/js/aws-sdk-2.0.0-rc4.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="{!URLFOR($Resource.AsyncJS)}"></script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-size: 12px;
}
#fileSelectArea {
margin: 5px 0;
padding: 0;
font-weight: bold;
}
#fileList {
height: 170px;
border: 5px solid #fff;
box-sizing: border-box;
overflow: auto;
}
#fileList.over {
border: 5px dashed #aaa;
}
#fileList table {
width: 100%;
font-size: 12px;
}
#fileList table tr {
border-bottom: 1px solid #ccc;
}
#fileList table tr.header {
background-color: #eee;
}
#loading {
display: none;
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
color: white;
font-size: 24px;
font-weight: bold;
text-align: center;
line-height: 200px;
}
</style>
<script>
var bucketName = 'salesforce-bucket';
var bucket;
$(function() {
initAWSCredentials();
initEventHandlers();
updateFileList();
});
function initAWSCredentials() {
var assertion = $('#samlResponse').val();
if (!assertion) {
alert('No SAML assertion found');
return;
}
AWS.config.credentials = new AWS.SAMLCredentials({
RoleArn: 'arn:aws:iam::119301928242:role/SalesforceUserRole',
PrincipalArn: 'arn:aws:iam::119301928242:saml-provider/SalesforceIdP',
SAMLAssertion: assertion
});
bucket = new AWS.S3({ params: { Bucket: bucketName } });
}
function updateFileList(recordId) {
startLoading();
bucket.listObjects({ Prefix: getPrefix() }, function(err, resp) {
stopLoading();
if (err) { alert(err.message); throw err; }
$('#fileList').empty();
if (resp.Contents.length === 0) {
$('#fileList').text('No files');
} else {
var table = $('<table>').appendTo($('#fileList'));
var tr = $('<tr class="header">');
$('<th style="width:50px">').text('').appendTo(tr);
$('<th>').text('File Name').appendTo(tr);
$('<th style="width:150px">').text('Last Modified').appendTo(tr);
tr.appendTo(table);
$.each(resp.Contents, function(i, content) {
var key = content.Key;
var fileName = key.split('/').pop();
var tr = $('<tr>').data('key', key).data('fileName', fileName);
var deleteLink = $('<a class="delete-link" href="#">').text('Delete');
$('<td style="width:50px">').append(deleteLink).appendTo(tr);
var viewLink = $('<a class="view-link" href="#">').text(fileName);
$('<td>').append(viewLink).appendTo(tr);
$('<td style="width:150px">').text(formatDate(content.LastModified)).appendTo(tr);
tr.appendTo(table);
});
}
});
}
function initEventHandlers() {
function dragEnter(e) {
e.stopPropagation();
e.preventDefault();
}
function dragOver(e) {
$(this).addClass('over');
e.stopPropagation();
e.preventDefault();
}
function dragLeave(e) {
$(this).removeClass('over');
e.stopPropagation();
e.preventDefault();
}
function drop(e) {
$(this).removeClass('over');
e.stopPropagation();
e.preventDefault();
if (e.originalEvent.dataTransfer) {
var dt = e.originalEvent.dataTransfer;
var files = dt.files;
uploadFiles(files);
}
}
var dropbox = $("#fileList");
dropbox.on("dragenter", dragEnter);
dropbox.on("dragover", dragOver);
dropbox.on("dragleave", dragLeave);
dropbox.on("drop", drop);
var fileSelect = $('#fileSelect');
fileSelect.on('change', function(e) { uploadFiles(this.files); });
var fileList = $('#fileList');
fileList.on('click', 'a.view-link', function(e) {
var key = $(this).parents('tr').data('key');
bucket.getSignedUrl('getObject', { Key: key }, function (err) {
if (err) { alert(err.message); throw err; }
window.open(url, '_blank');
});
});
fileList.on('click', 'a.delete-link', function(e) {
var key = $(this).parents('tr').data('key');
var fileName = $(this).parents('tr').data('fileName');
if (confirm('Are you sure you want to delete the file "' + fileName + '" ?')) {
startLoading();
bucket.deleteObject({ Key: key }, function (err) {
stopLoading();
if (err) { alert(err.message); throw err; }
updateFileList();
});
}
});
}
function uploadFiles(files) {
if (files && files.length > 0) {
startLoading();
async.forEach(files, function(file, cb) {
var params = {Key: getPrefix() + file.name, ContentType: file.type, Body: file};
bucket.putObject(params, cb);
}, function (err) {
stopLoading();
$('#fileSelect').val('');
if (err) { alert(err.message); throw err; }
updateFileList();
});
}
}
function startLoading() {
$('#loading').show();
}
function stopLoading() {
$('#loading').hide();
}
function getPrefix() {
try {
return window.parent.recordId ? window.parent.recordId + '/' : '';
} catch(e) {
return '';
}
}
function formatDate(d) {
d = new Date(d);
return d.getFullYear() + '/' + (d.getMonth()+1) + '/' + d.getDate()+ ' ' + d.getHours() + ':' + d.getMinutes();
}
</script>
</head>
<body>
<input type="hidden" id="samlResponse" value="{!$CurrentPage.parameters.SAMLResponse}" />
<div id="fileSelectArea">Select Uploading Files:
<input id="fileSelect" type="file" multiple="multiple" />
</div>
<div id="fileList"></div>
<div id="loading">Loading ...</div>
</body>
</html>
</apex:page>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment