Created
October 16, 2012 16:06
-
-
Save JAndritsch/3900258 to your computer and use it in GitHub Desktop.
jQuery File Uploader with nginx setup - Custom Example
This file contains 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
<!DOCTYPE HTML> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>jQuery File Upload Example</title> | |
<style> | |
table { | |
width: 90%; | |
border: 1px solid #ccc; | |
color: #888; | |
margin-top: 20px; | |
padding: 10px 0px 10px 0px; | |
} | |
tr { | |
height: 30px; | |
border-bottom: 1px solid #ccc; | |
} | |
td.filename { | |
width: 25%; | |
} | |
.bar { | |
background-color: green; | |
display: block; | |
text-align: center; | |
} | |
td.progress { | |
width: 20%; | |
border: 1px solid #ccc; | |
padding: 0px; | |
color: #fff; | |
font-weight: bold; | |
} | |
td.start { | |
width: 10%; | |
} | |
td.cancel { | |
width: 30%; | |
} | |
th { | |
text-align: left; | |
} | |
</style> | |
</head> | |
<body> | |
<input id="fileupload" type="file" name="files[]" data-url="http://localhost:8080/upload" multiple> | |
<button id="start_upload" type="button">Start uploads</button> | |
<button id="stop_uploads" type="button">Cancel all uploads</button> | |
<span>Total progress: <span id="total_progress">0%</span></span> | |
<table id="files"> | |
</table> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script> | |
<script src="/blueimp/js/vendor/jquery.ui.widget.js"></script> | |
<script src="/blueimp/js/jquery.iframe-transport.js"></script> | |
<script src="/blueimp/js/jquery.fileupload.js"></script> | |
<script src="https://raw.github.com/carlo/jquery-base64/master/jquery.base64.min.js" type="text/javascript"></script> | |
<script> | |
$(function () { | |
// holds the files and their current state. storing the objects here allows me to easily set up start/stop controls rather | |
// than have the calls fire automatically when a file is added | |
var files = []; | |
var calculateProgress = function(data) { | |
var value = parseInt(data.loaded / data.total * 100, 10) || 0; | |
return value + "%"; | |
}; | |
var fileName = function(data) { | |
return data.files[0].name; | |
}; | |
var uploadedFilePath = function(data) { | |
return JSON.parse(data.result)[".path"]; | |
}; | |
var cancelUpload = function(index) { | |
if (files[index]) { | |
files[index].jqXHR.abort(); | |
} | |
}; | |
var startUpload = function(index) { | |
// starts the upload for file at "index". If the context for this object has "uploadedBytes", | |
// the upload will continue from the previous range rather than start over completely | |
var data = files[index]; | |
var context = data.context; | |
data.uploadedBytes = parseInt($(context).attr("uploadedBytes"), 10); | |
data.data = null; | |
$(data).submit(); | |
}; | |
var cancelAllUploads = function() { | |
$(files).each(function(index, file) { | |
cancelUpload(index); | |
}); | |
}; | |
var startAllUploads = function() { | |
$(files).each(function(index, data) { | |
startUpload(index); | |
}); | |
}; | |
var createProgressBar = function(progress) { | |
return '<span class="bar" style="width: ' + progress + '">' + progress + '</span>'; | |
}; | |
var maxChunkSize = 500000; | |
$('#fileupload').fileupload({ | |
maxChunkSize: maxChunkSize, | |
multipart: false, | |
add: function (e, data) { | |
var progress = calculateProgress(data); | |
var filename = fileName(data); | |
var index = $("#files tr").length; | |
var cancelButton = $('<button type="button" data-file="' + index + '">Cancel upload</button>'); | |
var startButton = $('<button type="button" data-file="' + index + '">Start upload</button>'); | |
cancelButton.click(function() { | |
cancelUpload($(this).attr("data-file")); | |
}); | |
startButton.click(function() { | |
startUpload($(this).attr("data-file")); | |
}); | |
var row = $('<tr><td class="filename"></td><td class="progress"></td><td class="start"></td><td class="cancel"></td>'); | |
var sessionID = new Date().getTime() + '_' + $.base64.encode(filename).replace(/\+|=|\//g, ''); | |
$(row).find(".filename").text(filename); | |
$(row).find(".progress").html(createProgressBar(progress)); | |
$(row).find(".start").append(startButton); | |
$(row).find(".cancel").append(cancelButton); | |
$(row).attr("sessionID", sessionID); | |
$(row).appendTo("#files"); | |
data.context = row; // assign the row to the context | |
files.push(data); // add the object to our files container | |
}, | |
done: function(e, data) { | |
// Just a simple method for displaying the path to the uploaded file | |
var pattern = new RegExp(/[a-zA-Z0-9]\/\w*$/); | |
var file = uploadedFilePath(data).match(pattern); | |
var filepath = '<a href="/images/' + file + '">' + file + '</a>'; | |
data.context.find(".cancel").html(filepath); | |
}, | |
progress: function(e, data) { | |
var progress = calculateProgress(data); | |
data.context.find(".progress").html(createProgressBar(progress)); | |
}, | |
progressall: function (e, data) { | |
var progress = calculateProgress(data); | |
$("#total_progress").text(progress); | |
}, | |
beforeSend: function(e, files, index, xhr, handler, callback) { | |
var file = files.files[0]; | |
var filename = file.name; | |
var filesize = file.size; | |
var context = files.context[0]; | |
var sessionID = $(context).attr("sessionID"); | |
var loaded = files.uploadedBytes; | |
var end; | |
// because chunks that are larger than the filesize don't automatically resize | |
if (filesize < maxChunkSize) { | |
end = filesize - 1; | |
} else { | |
end = (loaded + files.chunkSize - 1); | |
} | |
// nginx requires the Content-Range header, as well as a few others. | |
var contentRange = "bytes " + loaded + "-" + end + "/" + filesize; | |
// store the last range uploaded on the context for resuming the upload later | |
$(context).attr("uploadedBytes", files.uploadedBytes); | |
e.setRequestHeader('Content-Disposition', 'attachment; filename="' + sessionID + '.' + filename.split('.').pop() + '"'); | |
e.setRequestHeader('Session-ID', sessionID); | |
e.setRequestHeader('Content-Range', contentRange); | |
e.setRequestHeader('X-Chunk-Index', files.chunkIndex); | |
e.setRequestHeader('X-Chunks-Number', files.chunksNumber); | |
} | |
}); | |
$("#start_upload").click(function() { | |
startAllUploads(); | |
}); | |
$("#stop_uploads").click(function() { | |
cancelAllUploads(); | |
}); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment