jQuery 文件上传:是不是可以使用提交按钮触发上传?

Posted

技术标签:

【中文标题】jQuery 文件上传:是不是可以使用提交按钮触发上传?【英文标题】:jQuery file upload: Is it possible to trigger upload with a submit button?jQuery 文件上传:是否可以使用提交按钮触发上传? 【发布时间】:2012-04-19 23:52:26 【问题描述】:

我正在使用 jQuery file upload 进行基于 AJAX 的上传。它总是在选择文件后开始上传。是否可以更改行为以使用“提交”按钮?我知道Issue #35,但选项beforeSend 似乎已被删除。

我使用的是Basic Plugin,而不是完整版。

也许我应该按照那里的建议切换到基于纯 XHR 的上传:jQuery Upload Progress and AJAX file upload。

【问题讨论】:

【参考方案1】:

在下载的示例中导航到js/jquery.fileupload-ui.js,您将拥有autoUpload,默认情况下设置为true,然后将其设置为“false”,然后您可以使用提交行为。

编辑:

试试这个基本实现:

 <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> 

【讨论】:

我使用的是基本插件,而不是完整版。我在基本插件中没有看到任何“-ui.js”。【参考方案2】:

如果你有按钮

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

你可以试试

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

编辑:根据 cmets 一个更好的答案考虑 off 以避免重复请求。 (也可以工作unbind,我不检查是否是bindunbind 但jquery 团队推荐onoff link 从1.7 开始)

【讨论】:

确保#up_btn 按钮不在#fileupload 表单中。 您可能还想使用one 而不是on(并在提交后重新绑定事件)以避免重复请求 这将有助于防止重复请求:@zykadelic 建议的$("#imgupload").unbind('click').on('click', function()data.submit();); @inye 是的。但该事件被多次绑定。 offon 按预期工作。在此处查看one 的示例:jsfiddle.net/jet8umej 这不允许上传多个文件。对于多文件上传,会为所有选定的文件调用 add 函数,因此它会删除以前文件的点击事件,最后执行最后一次注册的点击事件【参考方案3】:

您也可以在 jquery.fileupload.js

中找到

第 142 行有一个 'autoUpload' 选项。

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

【讨论】:

我不明白这如何提供问题的答案。除非您使用 UI 插件,否则您应该将 autoUpload 设置为 false 以在单击按钮时触发上传。但这只是简单的部分。然后你必须管理点击事件。【参考方案4】:

确保不要在每次添加文件时附加事件来堆叠事件。这样表单将被多次提交。

我会做这样的事情

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

注意 off() 方法删除所有以前附加的事件。

【讨论】:

我已经尝试了这两种情况,通过在表单和表单外放置按钮,在第一种情况下它发送两个请求然后重定向到索引页面,而在第二种情况下它发送一个请求但保持相同的新/编辑页面。我希望它发送一个请求并在成功创建时返回索引页面【参考方案5】:

使用添加模板跟随显示上传和下载必须这样做

$('#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();
        );
    ,
);

【讨论】:

它确实有效,但如果您选择多个文件,则进度条更新仅适用于最后一个。【参考方案6】:

您可以通过挂钩 add 事件来做到这一点。在那里,您可以阻止上传者执行其默认行为。 jquery-file-upload-docs 解释了这一点,但有点难找。

下面写在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.');
        
    );
);

实际上非常重要的是,您创建的提交按钮不在表单内!

【讨论】:

【参考方案7】:

这些答案都不适用于多个文件上传。我的案例涉及在评论线程中允许多个附件。所以我需要先保存评论获取id,然后上传并保存所有附件。这似乎是一件微不足道的事情,但是有了这个插件,它就不是那么直观了。我的解决方案在 jQuery 中使用自定义事件,效果很好。

当前接受的答案绑定到“添加”回调中按钮的单击事件,但“添加”回调为每个文件调用一次。如果每次都解绑所有事件,只会上传最后一个文件。

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

通过将提交按钮绑定到自定义名称,我们可以在提交图像之前进行任何我们想要的预处理。就我而言,它涉及提交评论并取回我在单独调用中所做的评论 ID。这段代码只是响应点击,但你可以在触发事件之前做任何你想做的事情。

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

您可以在触发事件时传递您想要的任何数据,因此它确实让您可以完全控制您的表单。

【讨论】:

这是一个更完整的解决方案。谢谢杰夫! 按钮是否需要在表单之外?我有几个按钮来触发相同的事件。但我找不到它工作。【参考方案8】:

这是我使用按钮实现文件上传的方式:

这是按钮:

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

这里是输入元素:

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

这里是 SaveInfo() 函数:

    //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');
        );
    

注意: 它可能不是很优雅,但它对我有用。 这也会将表单中的所有字段发送到服务器。 如果文件也在上传,这只会发送表单中的字段。如果文件不存在,则不会将表单数据发送到服务器!虽然我没有用多个文件对其进行测试,但这种方法也可以扩展为多个文件。当我尝试它时,我会用信息更新这篇文章。

【讨论】:

以上是关于jQuery 文件上传:是不是可以使用提交按钮触发上传?的主要内容,如果未能解决你的问题,请参考以下文章

使用 jquery AJAX 和 FormData 上传文件

取消表单文件上传提交

Krajee 文件输入在表单提交时提交文件

在 JQuery 委托中触发表单提交

ajaxsubmit怎么提交文件

Jquery Blueimp 文件上传回调