【问题标题】:blueimp jQuery-File-Upload - How do I submit form without files attached?blueimp jQuery-File-Upload - 如何提交没有附加文件的表单?
【发布时间】:2014-02-13 17:05:12
【问题描述】:

我找到了在提交文件上传表单时如何添加额外表单数据的解决方案。这个问题是如果没有文件要上传,如何上传附加数据。

我在任务管理应用程序中使用 blueimp jquery-file-upload 来拖放文件并将它们附加到任务。

脚本已初始化并设置为在附加文件时不会自动上传。在fileuploadadd 回调中,我将data.submit() 附加到我的submit 事件处理程序。这实现了我们在一个 POST 请求中提交任务数据和文件。

在添加文件之前,我无法访问文件上传data 以使用data.submit() 函数。我想出了一个解决方法,在页面加载时添加一个空文件(然后将其删除),这将触发绑定 data.submit() 到提交按钮。问题是插件在尝试遍历空文件数组时返回错误。如果您在提交表单之前添加了文件然后将其删除,也会出现此问题。

我一直在寻找解决此问题的方法,并且看起来高高在低,但在(恕我直言)糟糕的文档中找不到任何东西。

看看我下面的代码:

    $('#post_task').fileupload({
        autoUpload: false,
        singleFileUploads: false,
        disableImagePreview: true,
    }).on('fileuploadadd', function (e, data) {
        $.each(data.files, function (index, file) {
            var filename = file.name,
                filesize = bytesToSize(file.size) 
                ext = filename.substr(filename.lastIndexOf('.')+1,5),
                icon = '<i class="sprite_file sprite_file-file_extension_'+ext+'"></i>',
                node = $('<li/>').append($('<span/>').html(icon + filename + ' ' + filesize + '<a href="#">&times</a>')).attr('data-index',index);

            node.find('a').click(function(e){
                e.preventDefault();
                var $self = $(this),
                    $listItem = $self.parents('li'),
                    listIndex = $listItem.attr('data-index');
                $listItem.remove();
                $('#files li').attr('data-index',function(index){return index;});
                data.files.splice(listIndex,listIndex);
                console.log(data);
                vardata = data;
            });
            $('#files').append(node);
        });
        $('#post_task').unbind('submit').submit(function(ev){
            ev.preventDefault();
            data.submit();
        });
    });

【问题讨论】:

  • 我也有同样的要求。文件上传只是表单的可选部分,因此表单需要能够在没有选择上传文件的情况下提交。

标签: javascript jquery jquery-file-upload blueimp


【解决方案1】:

我遇到了同样的问题,如果没有文件,我最终在提交之前添加了一个空文件。

$("#fileupload").fileupload('add', {
    files: ['']
});

这在我的情况下非常有效,当提交的文件为空时,后端会收到 POST。

对于大多数浏览器(经过测试的 Chrome 和 FF),我的后端将不会收到任何文件(null),但对于 IE8,会有一个大小为 0 的文件。我还没有使用任何其他 IE 对其进行测试。

【讨论】:

    【解决方案2】:

    我刚刚制作了两个单独的处理程序,如下所示:

    $('#avatar').fileupload({
                singleFileUploads: true,
                multipart        : true,
                dataType         : 'json',
                autoUpload       : false,
                url              : config.settings.api + 'services/user/updateByActivationKey',
                type             : 'POST',
                add              : function (e, data) {
    
                    submitbtn.on("click", function () {
                        console.log('submitting with image');
                        data.submit();
                    });
                },
                done             : function (result) {
    
                    console.log(result);
                    if (!result.error) {
                        $('#modal-account-activated-success').modal('show');
                        $("#submitbtn").removeAttr('disabled');
                        $('#mercname').html('');
                        window.setTimeout(function () {
                            window.location.href = config.settings.user_url;
                        }, 3000);
    
                    } else {
                        //analytics.track('completeProfileError', {
                        //  error        : JSON.parse(result.responseText).error,
                        //  activationKey: sessionStorage.getItem("activationkey")
                        //});
                        $('#modal-account-activated-error').modal('show');
                        $('#submitloader').html('');
                        $("#submitbtn").removeAttr('disabled');
                    }
                }
                ,
                fail             : function (e) {
                    //analytics.track('completeProfileError', {
                    //  error        : e,
                    //  activationKey: sessionStorage.getItem("activationkey")
                    //});
                    $('#errormessage').html(JSON.parse(e.responseText).error.messages[0]);
                    $('#modal-account-activated-error').modal('show');
                    $('#submitloader').html('');
                    $("#submitbtn").removeAttr('disabled');
    
                }
            });
    
            //if no image was uploaded
            submitbtn.on("click", function () {
                if ($('#preview').html().length < 1) {
                    console.log('submitting without image');
    
                    $.ajax({
                        url       : config.settings.api + 'services/user/updateByActivationKey',
                        type      : 'POST',
                        data      : JSON.stringify({
                            'email'                     : $("#email").val(),
                            'activationKey'             : $("#activationKey").val(),
                            'firstName'                 : $("#firstname").val(),
                            'lastName'                  : $("#name").val(),
                            'password'                  : $("#password").val(),
                            'gender'                    : $("#gender").val(),
                            'birthdate'                 : $("#birthdate").val(),
                            'acceptedTermsAndConditions': $("#checkbox-accept-terms").val(),
                            'allowsDirectMarketing'     : $("#checkbox-allow-marketing").val()
    
                        }),
                        beforeSend: function (xhr) {
                            xhr.setRequestHeader("Content-Type", "application/json");
                        },
                        success   : function (result) {
                            console.log(result);
                            if (!result.error) {
                                $('#modal-account-activated-success').modal('show');
                                $("#submitbtn").removeAttr('disabled');
                                $('#mercname').html('');
                                window.setTimeout(function () {
                                    window.location.href = config.settings.user_url;
                                }, 3000);
    
                            } else {
                                //analytics.track('completeProfileError', {
                                //  error        : JSON.parse(result.responseText).error,
                                //  activationKey: sessionStorage.getItem("activationkey")
                                //});
                                $('#modal-account-activated-error').modal('show');
                                $('#submitloader').html('');
                                $("#submitbtn").removeAttr('disabled');
                            }
                        },
                        error     : function (e) {
                            //analytics.track('completeProfileError', {
                            //  error        : e,
                            //  activationKey: sessionStorage.getItem("activationkey")
                            //});
                            $('#errormessage').html(JSON.parse(e.responseText).error.messages[0]);
                            $('#modal-account-activated-error').modal('show');
                            $('#submitloader').html('');
                            $("#submitbtn").removeAttr('disabled');
                        }
                    })
                }
            });
    

    【讨论】:

      【解决方案3】:

      @Hirshy 和@Luk,你的解决方案真的很优雅,而且很有魅力。文件输入字段甚至不会发送到服务器,因此很容易确定文件何时在有效负载中。

      在我的 Angular 应用程序中,我有一个视图,用于添加新文档和一些相关数据,以及用于编辑数据和/或上传替换文档。

      这是我的解决方案:

      /*------------------------------------------------------------------------*/
      /* Prepare file uploader.                                                 */
      /*                                                                        */
      /* jQuery-File-Upload does not submit a form unless a file has been       */
      /* selected. To allow this, we manually add an empty file to be uploaded, */
      /* which makes the submit handler available, and we replace the submit    */
      /* handler with one that will submit the form without a selected file.    */
      /*                                                                        */
      /* see: http://stackoverflow.com/q/21760757/2245849.                      */
      /*------------------------------------------------------------------------*/
      var uploadForm = $('#DocumentForm');
      var fileInput  = $('#DocumentForm input:file');
      
      $scope.uploadOptions = 
        {
        url:              Services.Documents.uploadRoute,
        autoUpload:       false,
        dropZone:         uploadForm,
        fileInput:        fileInput,
        replaceFileInput: false
        };
      
      /*---------------------------------------------------------------*/
      /* Initialize the uploader. This must be done with the options   */
      /* or an error will be thrown when an empty file is added below. */
      /* It is also necessary to initialize with the options here as   */
      /* well as in the element html or the results are unpredictable. */
      /*---------------------------------------------------------------*/
      uploadForm.fileupload($scope.uploadOptions);
      
      /*--------------------------------------------------------------------*/
      /* File processing is called in the default add handler and this      */
      /* handler is called after a successful add. It displays the file     */
      /* name in the drop zone, sets the document name for a new document,  */
      /* and sets the submit handler to submit the form with file and data. */
      /*                                                                    */
      /* If editing a document, a dummy empty file object is manually       */
      /* added to make the submit handler available so the user can make    */
      /* data changes without uploading a new document.                     */
      /*--------------------------------------------------------------------*/
      uploadForm.bind("fileuploadprocessdone", function(e, data) 
        {
        /*------------------------------------------------------------*/
        /* Get the user selected file object and display the name.    */
        /* Set the document name to the file name if not already set. */
        /*------------------------------------------------------------*/
        if (data.files[0].name)
          {
          $scope.document.file = data.files[0];
          if (!$scope.document.name)
            $scope.document.name = $scope.document.file.name;
          MessageService.clear();
          }
      
        /*--------------------------------------*/
        /* If this is the dummy file add, reset */
        /* 'acceptFileTypes' to global config.  */
        /*--------------------------------------*/
        else  
          delete $scope.uploadOptions.acceptFileTypes;
      
        /*------------------------------------------------------------*/
        /* Set the submit handler. We have to do this every time a    */
        /* file is added because 'data' is not passed to the handler. */
        /*------------------------------------------------------------*/
        uploadForm.unbind('submit').submit(function(e)
          {
          e.preventDefault();
          data.submit();
          });
        });
      
      /*---------------------------------------------------------------------------*/
      /* If we get here, the file could not be added to the process queue most     */
      /* likely because it is too large or not an allowed type. This is dispatched */
      /* after the add event so clear the current file and show the error message. */
      /*---------------------------------------------------------------------------*/
      uploadForm.bind("fileuploadprocessfail", function(e, data) 
        { 
        $scope.document.file = null;
        MessageService.notice(data.files[data.index].error);
        });
      
      /*-----------------------------------------------------------------*/
      /* Add a dummy empty file if not a new document so the submit      */
      /* handler is set and the user does not have to upload a document. */
      /*-----------------------------------------------------------------*/
      if (!$scope.new_document)
        {
        $scope.uploadOptions.acceptFileTypes = null;
        uploadForm.fileupload('add', { files: [{}] });
        }
      

      更新

      如果服务器返回失败状态,uploadForm.fileupload('add', { files: [''] }); 将导致在浏览器中抛出异常。 JFU 尝试分配 data.files[0].error 并且 data.files[0] 不存在。

      通过分配空数组而不是空字符串可以很好地解决问题:uploadForm.fileupload('add', { files: [[]] });

      我已经更新了上面的例子。

      2/29/16 更新

      结果我确实想限制文件类型,所以我修改了我的脚本以在添加虚拟文件之前清除“acceptFileTypes”属性并在添加处理程序中重置它。还发现我无法访问添加处理程序中的进程错误,因此将其替换为“fileuploadprocessdone”并处理了“fileuploadprocessfail”中的错误。

      我已经更新了上面的示例,但我们仍在使用 JFU 5.42.0。

      重要

      我正在使用 5.42.0,这是一个非常旧的 JFU 版本。我没有编写此代码,并且我的第一次升级尝试失败了。当我升级时,我会更新这个解决方案。**

      【讨论】:

        【解决方案4】:

        试试这个 puglin simpleUpload,不需要表单

        HTML:

        <input type="file" name="arquivo" id="simpleUpload" multiple >
        <button type="button" id="enviar">Enviar</button>
        

        Javascript:

        $('#simpleUpload').simpleUpload({
          url: 'upload.php',
          trigger: '#enviar',
          success: function(data){
            alert('Envio com sucesso');
        
          }
        });
        

        【讨论】:

          猜你喜欢
          • 2012-04-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-17
          • 1970-01-01
          • 2015-03-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多