Blueimp File Upload Plugin uploads only once
Asked Answered
S

2

10

I have this strange issue and I've tried several solutions (even implementing the same as the Basic Plus demo on their website). I can upload files just fine, single or multiple. They upload on a click of the individual item, or a "Upload All" button. The problem is trying to add additional files before or after uploading. The file upload plugin will not even detect that these files are changing in the file input, so it never fires the "fileuploadadd" event, and requires me to refresh the page in order to upload more files. I'm wondering whether the fileupload change event is being lost somewhere, but I cannot for the life of me figure out where.

Also, does the blueimp file upload plugin require a specific return format of JSON? At the minute, I'm just returning "{\"status\":\"success\"} if the uploads are a success, and a similar error message. EDIT: Changing the response format to examples shown by blueimp had no effect.

Here's some code for the uploader I'm using. Note that I'm currently using ASP.NET and jQuery 2.0.3, and jQuery UI 1.9.2.

function initFileUploader() {
    //initProgressBars();
    $(upload_progressbar_title).css('display', 'none');
    $(upload_progressbar).css('display', 'none');
    $(upload_upload).on('click', function () {
        $(upload_progressbar).css('display', 'block');
        $(upload_progressbar_title).css('display', 'block');
        $('.uploadbtn').click();
    });
    $(upload_browse).on('click', function () {
        $(upload_file).click();
        return false;
    });

    $.guid = 0;
    console.log('initialising file upload');

    var uploadButton = $('<input type="button" id="button" />')
        .addClass('button tiny').addClass('uploadbtn')
        .prop('disabled', true)
        .val('Processing...');

    var uploadCon = $('<div class="small-4  medium-6 large-6 columns progresscontainer" />')
            .append('<div class="progressbar" />')
            .append('<label class="progressbarlabel">Not uploading</label>');

    uploadCon.append($(uploadButton).on('click', function () {
        var $this = $(this),
            data = $this.parent().data();
        $this
            .off('click')
            .val('Abort')
            .on('click', function () {
                $this.remove();
                data.abort();
            });
        data.submit().always(function () {
            $this.remove();
        }).success(function (result, textStatus, jqXHR) { console.log("Result: " + result + " - TextStatus " + textStatus); })
        .error(function (jqXHR, textStatus, errorThrown) { console.log("Error: " + errorThrown + " - TextStatus " + textStatus); })
        .complete(function (result, textStatus, jqXHR) { console.log("Result: " + result + " - TextStatus " + textStatus); });
    }));

    $(upload_file).fileupload({
        dataType: 'json',
        autoUpload: false,
        acceptFileTypes: /(\.|\/)(pdf|jpe?g|png|doc|docx)$/i,
        maxFileSize: 5000000, // 5 MB
    }).on('fileuploadadd', function (e, data) {
        var uniqueId = $.guid++;
        data.context = $('<div id="div_upload_dcon_' + uniqueId +'" class="row"/>').appendTo(upload_filescon);
        $.each(data.files, function (index, file) {
            file.uniqueId = uniqueId;
            var node = $('<div id="div_fname" class="small-6 medium-4 large-4 columns"/>')
                    .append($('<span/>').text(file.name));
            if (!index) {
                data.url = baseUrl + 'PostUploadFile?fileName=' + data.files[index].name + '&refId=' + ClientRefId + '&upbyid=' + ClientUserId + '&ticketId=' + globalTicketId;
                var contentNode = (uploadCon.clone(true).data(data));
            }
            node.appendTo(data.context);
            $(contentNode).appendTo(data.context);
            $(upload_file).on('change', function () {
                alert('changing fileinput');
            });
        });
    }).on('fileuploadstart', function (e, data) {
        initProgressBars();
    }).on('fileuploadchange', function (e, data) {
        alert('changing');
    }).on('fileuploadprocessalways', function (e, data) {
        var index = data.index,
            file = data.files[index],
            node = $(data.context.children()[index]);
        if (file.error) {
            console.log(file.error));
        }
        if (index + 1 === data.files.length) {
            $('.uploadbtn').val('Upload').prop('disabled', !!data.files.error);
        }
    }).on('fileuploadprogress', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        $('#div_upload_dcon_' + data.files[0].uniqueId).progressbar('value', progress);
    }).on('fileuploadprogressall', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        $(upload_progressbar).progressbar('value', progress);
    }).on('fileuploaddone', function (e, data) {
        getTicketContent(globalTicketId);
    }).on('fileuploadstop', function (e, data) {
        $(upload_file).val('');
    }).on('fileuploadfail', function (e, data) {
        $.each(data.files, function (index, file) {
            var error = $('<span class="text-danger"/>').text('File upload failed.');
            $(data.context.children()[index])
                .append('<br>')
                .append(error);
        });
    });
}
Skinflint answered 12/5, 2014 at 16:13 Comment(0)
S
19

Well, after a night's sleep and more thinking about it, I specified this option

replaceFileInput: false,

during the file upload initialisation. And guess what, it works as intended now. I'm guessing that the file input was being lost because the fileupload clones the control by default after an upload or change.

Thanks for any consideration anyone may have given this, I hope it comes in handy for someone else in the future.

Skinflint answered 13/5, 2014 at 8:20 Comment(3)
Great! Exactly the same problem I was having.Harveyharvie
It's year 2016, and you're still saving our butts!Bronchitis
Gah. Thank you! WHY was this "feature" implemented in the first place?! It ruins the event handlers that were previously attached to the file input element!Calandracalandria
B
3

It's been two years since the original answer, but I just figured this out for my own case (:

If you use replaceFileInput: false, the code will not work in IE9, which does not support the newer file upload APIs. According to the documentation the fallback support for this browser depends on an "iframe transport" that requires the file input element be replaced each time. Reading that was the big clue for me.

What's really killing you is this:

$(upload_browse).on('click', function () {
  $(upload_file).click();
  return false;
});

You are assuming that upload_file is still the same element, but it's been replaced with a clone. You're firing a click event on the old file input element. It exists, so you get the system browse dialog, but it's not hooked up to any plumbing.

So the correct solution with full IE9 support is to use "find" to locate upload_file anew each time this click handler is fired. You didn't include your code for setting upload_file, so I don't know what the correct selector would be in your case, but it would look something like this:

$(upload_browse).on('click', function () {
  // You should use a more specific selector, better yet use
  // find() to locate it inside some div you know is "in scope" so
  // you don't fire every file input on the page. Just an example
  $('input[type=file]').click();
  return false;
});
Burgin answered 25/5, 2016 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.