Skip to content

Instantly share code, notes, and snippets.

@JAndritsch
Created October 16, 2012 16:06

Revisions

  1. JAndritsch revised this gist Oct 17, 2012. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion example.html
    Original file line number Diff line number Diff line change
    @@ -198,7 +198,6 @@
    $(context).attr("uploadedBytes", files.uploadedBytes);

    e.setRequestHeader('Content-Disposition', 'attachment; filename="' + sessionID + '.' + filename.split('.').pop() + '"');
    e.setRequestHeader('Content-Type', 'application/octet-stream');
    e.setRequestHeader('Session-ID', sessionID);
    e.setRequestHeader('Content-Range', contentRange);
    e.setRequestHeader('X-Chunk-Index', files.chunkIndex);
  2. @invalid-email-address Anonymous created this gist Oct 16, 2012.
    221 changes: 221 additions & 0 deletions example.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,221 @@
    <!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> &nbsp;
    <button id="stop_uploads" type="button">Cancel all uploads</button>
    &nbsp;&nbsp;&nbsp;&nbsp;<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('Content-Type', 'application/octet-stream');
    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>