27

I'm using jQuery file upload for AJAX-based uploads. It always starts uploading after a file is selected. Is it possible to change the behavior to use the "submit"-button? I am aware of Issue #35, but the Option beforeSend seems to have been removed.

I am using the Basic Plugin, not the full version.

Maybe I should just switch to plain-XHR-based uploading as suggested there: jQuery Upload Progress and AJAX file upload.

Community
  • 1
  • 1
koppor
  • 14,964
  • 11
  • 100
  • 141

8 Answers8

49

if you have the button

<button id="up_btn">Upload</button>

You can try with

$('#fileupload').fileupload({
    dataType: 'json',
    add: function (e, data) {            
        $("#up_btn").off('click').on('click', function () {
            data.submit();
        });
    },
});

EDIT: according to comments a better answer considere off to avoid duplicated requests. (also work unbind, I do not check if is bind and unbind but jquery team recommend on and off link since 1.7)

inye
  • 1,718
  • 1
  • 22
  • 28
  • 2
    Make sure the #up_btn button is not in #fileupload form. – krizajb Apr 26 '14 at 08:12
  • 2
    You also probably want to use `one` instead of `on` (and rebind the event post-submit) to avoid duplicated requests – zykadelic Jun 02 '14 at 20:47
  • 5
    This will work to prevent duplicate requests: `$("#imgupload").unbind('click').on('click', function(){data.submit();});` as @zykadelic suggested – John the Ripper Jun 25 '14 at 12:23
  • @inye Yes. But the event was bound multiple times. `off` and `on` worked like expected. See an example with `one` here: http://jsfiddle.net/jet8umej/ – schmijos Dec 04 '14 at 11:50
  • If the button is inside the form, you could do something like this: `$("#up_btn").off('click').on('click', function (event) { event.preventDefault(); data.submit(); });` – Marian Oct 28 '15 at 12:10
  • 3
    This does not allow uploading of multiple files. For multiple file upload, add function is called for all selected files and hence it removes the click event of previous files and in the end last registered click event is executed – Ajinkya Pisal Feb 17 '16 at 14:40
  • @AjinkyaPisal See my answer for handling multiple files. – Jeff Ryan Jul 07 '16 at 01:26
  • I have tried both cases, by placing button in form and outside form, in first case it send two request and then redirect to index page while is second case it sends one request but keep on the same new/edit page. I want it to send one request and go back to index page on successful create – Muhammad Faisal Iqbal Oct 21 '16 at 11:31
  • @MuhammadFaisalIqbal better ask a new question and put your code to see more details. – inye Oct 21 '16 at 13:44
  • @inye I have tried this twice in such cases and people are ready to mark it duplicate just as they see the question. OK, Trying once again. – Muhammad Faisal Iqbal Oct 21 '16 at 13:53
  • @MuhammadFaisalIqbal maybe you have problem with your javascript selector (duplicated, wrong hierarchy, etc). – inye Oct 22 '16 at 23:01
  • @inye I asked a new question at https://stackoverflow.com/questions/40179378/jquery-file-upload-sending-two-request-on-data-submit kindly have a look – Muhammad Faisal Iqbal Oct 24 '16 at 13:58
  • i followed your solution but getting error "Uncaught RangeError: Maximum call stack size exceeded". Please suggest. – Kamlesh Mar 07 '20 at 11:05
  • @Kamlesh this is other problem. Did you see https://stackoverflow.com/a/6095695/2144445 ? – inye Mar 09 '20 at 18:34
10

None of these answers will work for multiple file uploads. My case involved allowing multiple attachments in a comment thread. So I needed to save the comment first to get the id, and then upload and save all the attachments. This seems like a trivial thing, but with this plugin its not that intuitive. My solution uses custom events in jQuery, and works great.

The currently accepted answer binds to the click event of a button in the 'add' callback, but the 'add' callback is called once for each file. If you unbind all the events each time only the last file will upload.

$('#fileupload').fileupload({
    dataType: 'json',
    add: function (e, data) {
        $("#up_btn").on('customName', function (e) {
            data.submit();
        });
    },
});

By binding the submit button to a custom name, we can do whatever preprocessing we want before submitting the images. In my case it involved submitting the comment and getting back the comment id which I did in a separate call. This code just responds to the click, but you can do whatever you want before triggering the event.

$("#up_btn").on('click', function (e) {
    e.preventDefault();
    $("#up_btn").trigger( "customName");
});

You can pass any data you want when you trigger the event, so it really gives you complete control over your form.

Prafulla Kumar Sahu
  • 7,813
  • 7
  • 46
  • 85
Jeff Ryan
  • 567
  • 1
  • 7
  • 19
5

You can also find in jquery.fileupload.js

There is an 'autoUpload' option in line 142.

uploadedBytes: undefined,
// By default, failed (abort or error) file uploads are removed from the
// global progress calculation. Set the following option to false to
// prevent recalculating the global progress data:
recalculateProgress: true,
// Interval in milliseconds to calculate and trigger progress events:
progressInterval: 100,
// Interval in milliseconds to calculate progress bitrate:
bitrateInterval: 500,
// By default, uploads are started automatically when adding files:
autoUpload: true    // <<---------- here
Phillip Lee
  • 156
  • 3
  • 6
  • I don't see how this provide an answer to the question. Unless you are using the UI plugin, you should set the autoUpload to false to trigger the upload when clicking on a button. But that's just the easy part. Then you have to manage the click event. – greg Jun 21 '18 at 11:09
4

You can do that by hooking into the add event. There you prevent the uploader from doing its default behavior. The jquery-file-upload-docs explain that, but it's a bit hard to find.

The following is written in the blueimp basic uploader tutorial:

$(function () {
    $('#fileupload').fileupload({
        dataType: 'json',
        add: function (e, data) {
            data.context = $('<button/>').text('Upload')
                .appendTo(document.body)
                .click(function () {
                    data.context = $('<p/>').text('Uploading...').replaceAll($(this));
                    data.submit();
                });
        },
        done: function (e, data) {
            data.context.text('Upload finished.');
        }
    });
});

It actually is very important, that the submit button you're creating is not inside the form!

schmijos
  • 6,629
  • 3
  • 43
  • 50
3

Make sure not to stack events by attaching event every time the file is added. That way the form will be submitted multiple times.

I would do something like this

$('#fileupload').fileupload({
    dataType: 'json',
    add: function (e, data) {            
        $("#up_btn").off('click').on('click', function () {
            data.submit();
        });
    },
});

Notice the off() method to remove all previous attached events.

slob
  • 123
  • 1
  • 8
  • I have tried both cases, by placing button in form and outside form, in first case it send two request and then redirect to index page while is second case it sends one request but keep on the same new/edit page. I want it to send one request and go back to index page on successful create – Muhammad Faisal Iqbal Oct 21 '16 at 13:27
3

for using the add templates to follow showing upload and download must do it this way

$('#fileupload').fileupload({
    dataType: 'json',
    add: function (e, data) {
        var that = this;
     $.blueimp.fileupload.prototype.options.add.call(that, e, data);
        $("#up_btn").on('click', function () {
            data.submit();
        });
    },
});
Vladimir Salguero
  • 4,156
  • 2
  • 30
  • 39
  • It does work, but if you select more than one file, the progress bar update works just for the last one. – greg Jun 20 '18 at 11:33
0

In the downloaded sample Navigate to js/jquery.fileupload-ui.js and in that you will have autoUpload which is set true by default go ahead and it to "false" then you can use submit behaviour.

EDIT:

Try this for the basic implementation:

 <script>
    /*global $ */
    $(function() {


        $('.file_upload').fileUploadUI({
            url: 'FileUpload.ashx',
            method: 'POST',
            uploadTable: $('#files'),
            downloadTable: $('#files'),
            buildUploadRow: function (files, index) {
                return $('<tr><td>' + files[index].name + '<\/td>' +
                    '<td class="file_upload_progress"><div><\/div><\/td>' +
                    '<\/td><\/tr>');
            },
            buildDownloadRow: function(file) {
            return $('<tr id="file_'+file.name+'"><td>' + file.name + '<\/td>'
                + '<td class="file_uploaded">' +
                '<span class="ui-icon ui-icon-check"><\/span>' +
                '<\/td><\/tr>');

            }, beforeSend: function(event, files, index, xhr, handler, callBack) {
                if (files[index].size > 500000) {
                    handler.uploadRow.find('.file_upload_progress').html('<span class="ui-icon ui-icon-alert"><\/span>FILE TOO BIG!');
                    setTimeout(function() {
                        handler.removeNode(handler.uploadRow);
                    }, 10000);
                    return;
                }
                callBack();
            }
        });
    });
</script> 
coder
  • 14,595
  • 32
  • 107
  • 213
  • I'm using the basic plugin, not the full version. I don't see any "-ui.js" in the basic plugin. – koppor Apr 06 '12 at 11:16
0

Here is how I implemented file upload by using a button:

Here is the button:

 <button id="cmdSave" type="button" class="btn btn-primary" onclick="SaveInfo();">Save</button>

Here is the input element:

    <input id="fileupload" type="file" name="files[]" style="display: none;">

Here is the SaveInfo() function:

    //use this function to save Info with Attached file
    function SaveInfo() {
        // setup our wp ajax URL
        var action_url = document.location.protocol + '//' + document.location.host + '/SaveInfo';

        $('body').addClass('waiting');
        //get the file(s)
        var filesList = $('input[type="file"]').prop('files');

        //Initialize the file uploader
        $('#Editor').fileupload();           //Editor is the Id of the form

        //Along with file, this call internally sends all of the form data!!!
        $('#Editor').fileupload('add', {
            files: filesList,
            url: action_url
        })

        $('#Editor').bind('fileuploaddone', function (e, data) {
            e.preventDefault(); //stop default behaviour!
            if (data.result.status == 1) {  //saved!
                 //do something useful here...
            }
            $('body').removeClass('waiting');
        });

        // Callback for failed (abort or error) uploads:
        $('#Editor').bind('fileuploadfail', function (e, data) {
            e.preventDefault(); //stop default behaviour!
            $('body').removeClass('waiting');
        });
    }

Note: It may not be very elegant, but it works for me. This will also send all of the fields within the form to the server. This will ONLY send the fields within the form if the file is also being uploaded. If the file is not present, this will NOT send form data to the server! Although I did not test it with multiple files, this method may be expanded to do multiples as well. When I try it, I will update this post with the info.

Jay Twiss
  • 11
  • 5