簡體   English   中英

jQuery如何清潔我自己的上傳插件中的formData對象

[英]Jquery how clean formData object in my own upload plugin

我試圖創建自己的插件來通過ajax上傳文件。
如果上載后重新加載了包含輸入文件的頁面,則看起來工作正常。
如果上傳后沒有重新加載輸入文件所在的頁面(因為僅重新加載了ajax內容),則IE和Chrome出現問題,因為要上傳的文件被追加到之前剛上傳的文件中(使用Firefox可以)。
我嘗試通過在首次上傳后清除輸入文件來修復它,但是通過這種方式,然后使用IE和Chrome,我無法再上傳其他文件。

我的修復

complete: function () {
       defaults.onFinish.call(this);
       // If page where is the input file not reloaded
       // after upload files IE and Chrome not working
       $this.replaceWith($this.val('').clone(true));
       $this.val('');
}

實際上,每次上傳后我都會清理formData對象,但我無法執行此操作

我的插件

;(function ($, window, document, undefined) {

    // Function-level strict mode syntax
    'use strict';

    $.fn.ajaxUpload = function(options) {

        var defaults = {
            num_files       : 0,
            max_files       : 2,
            max_concurrent  : 10,
            max_filesize    : 1024 * 4096,
            php_max_size    : 1024 * 8192,
            allowed_types   : ['jpeg','jpg'],
            ajax_url        : 'action.php',
            var_name        : 'file',
            extra_fields    : {},
            onFinish        : function() {}
        };

        var options = $.extend(defaults, options);

        return this.each(function() {

            var $this = $(this);

            $this.on('change', function() {

                var files = $this[0].files;
                var len = files.length;
                var items = 0;
                var diff_files = parseInt(defaults.max_files - defaults.num_files - len);

                if(diff_files < 0) {
                    return false;
                }
                if(!maxUploadFiles(len, defaults.max_concurrent)) {
                    return false;
                }
                var formdata = new FormData();

                jQuery.each(files, function(i, file) {
                    if(!isOverSized(file, defaults.max_filesize)) {
                        return false;
                    }
                    if(!isAllowedTypes(file, defaults.allowed_types)) {
                        return false;
                    }
                    if(!totalFilesSize(file, defaults.php_max_size)) {
                        return false;
                    }

                    formdata.append(defaults.var_name + '['+i+']', file);
                    items++;
                });

                // Append extra data to formdata
                $.each(defaults.extra_fields, function(name, value) {
                    formdata.append(name, value);
                });

                // Check that files have passed all test
                if (len != items) { return false; }

                $.ajax({
                    url: defaults.ajax_url,
                    data: formdata,
                    cache: false,
                    contentType: false,
                    processData: false,
                    type: 'POST',
                    beforeSend: function () {
                    },
                    success: function(data) {
                        totalSize = 0;
                    },
                    complete: function () {
                        defaults.onFinish.call(this);

                        // If page where is the input file not reloaded
                        // after upload files IE and Chrome not working
                        //$this.replaceWith($this.val('').clone(true));
                        //$this.val('');
                    }
                });

            });
       });
    };

    var totalSize = 0;

    function totalFilesSize(file, php_max_size) {
        totalSize += file.size;
        if(totalSize > php_max_size) {
            totalSize = 0;
            return false;
        }
        return true;
    }
    function maxUploadFiles(len, max_concurrent) {
        if(len > max_concurrent) {
            return false;
        }
        return true;
    }
    function isAllowedTypes(file, allowed_types) {
        var ext = file.name.split('.').pop().toLowerCase();
        if(jQuery.inArray(ext, allowed_types) < 0) {
            return false;
        }
        return true;
    }
    function isOverSized(file, max_filesize) {
        if(file.size > max_filesize) {
            return false;
        }
        return true;
    }

})(jQuery, window, document);

根據您的說法,我應該做出改變來解決我的問題? 謝謝

編輯

我在完成時添加了這一行,並且似乎可以正常工作

$this.val('');
$this.wrap('<form>').parent('form').trigger('reset');
$this.unwrap();
$this.replaceWith($this.clone());

插件的問題是,您使用$this保留了對原始輸入的引用,然后嘗試將其替換為克隆。 因為您每次克隆都最好獲得一個新的引用,所以您應該取消綁定和綁定。

(function ($, window, document, undefined) {

    // Function-level strict mode syntax
    'use strict';

    $.fn.ajaxUpload = function (options) {

        var defaults = {
            num_files: 0,
            max_files: 2,
            max_concurrent: 10,
            max_filesize: 1024 * 4096,
            php_max_size: 1024 * 8192,
            allowed_types: ['jpeg', 'jpg'],
            ajax_url: 'action.php',
            var_name: 'file',
            extra_fields: {},
            onFinish: function () {}
        };

        var options = $.extend(defaults, options);

        var bindInput = function (elem) {
            var element = $(elem),
            bindFunc = function (evt) {

                var files = evt.currentTarget.files;
                var len = files.length;
                var items = 0;
                var diff_files = parseInt(defaults.max_files - defaults.num_files - len);

                 if (diff_files < 0) {
                     return false;
                 }
                 if (!maxUploadFiles(len, defaults.max_concurrent)) {
                     return false;
                 }
                 var formdata = new FormData();

                 jQuery.each(files, function (i, file) {
                     if (!isOverSized(file, defaults.max_filesize)) {
                         return false;
                     }
                     if (!isAllowedTypes(file, defaults.allowed_types)) {
                         return false;
                     }
                     if (!totalFilesSize(file, defaults.php_max_size)) {
                         return false;
                     }

                     formdata.append(defaults.var_name + '[' + i + ']', file);
                     items++;
                 });

                 // Append extra data to formdata
                 $.each(defaults.extra_fields, function (name, value) {
                     formdata.append(name, value);
                 });

                 // Check that files have passed all test
                 if (len != items) {
                     return false;
                 }

                 $.ajax({
                     url: defaults.ajax_url,
                     data: formdata,
                     cache: false,
                     contentType: false,
                     processData: false,
                     type: 'POST',
                     beforeSend: function () {},
                     success: function (data) {
                         totalSize = 0;
                     },
                     complete: function () {
                         defaults.onFinish.call(this);
                         var previous = $(evt.currentTarget);
                         previous.off('change', bindFunc);
                         var newElem = previous.val('').clone(true)
                         previous.replaceWith(newElem);
                         bindInput(newElem);

                     }
                 });

             };
             element.on('change', bindFunc);
         };

         return this.each(function () {
             bindInput(this)
         });
    };

    var totalSize = 0;

    function totalFilesSize(file, php_max_size) {
        totalSize += file.size;
        if (totalSize > php_max_size) {
            totalSize = 0;
            return false;
        }
        return true;
    }

    function maxUploadFiles(len, max_concurrent) {
        if (len > max_concurrent) {
            return false;
        }
        return true;
    }

    function isAllowedTypes(file, allowed_types) {
        var ext = file.name.split('.').pop().toLowerCase();
        if (jQuery.inArray(ext, allowed_types) < 0) {
            return false;
        }
        return true;
    }

    function isOverSized(file, max_filesize) {
        if (file.size > max_filesize) {
            return false;
        }
        return true;
    }

})(jQuery, window, document);

{編輯}

引發您問題的問題是每個文件上傳插件開發人員的噩夢。 在開發插件時,應注意,輸入標簽可能包含必須保留的插件使用者設置的其他樣式和事件處理程序,否則將破壞現有功能。

出於安全原因,無法使用javascript更改輸入類型文件的值。 在SO中有很多答案。 搜索clear + input + file並親自查看,最引人注目的是使用jQuery清除<input type ='file'/>

如您所見,基本上有兩種選擇:

  1. 克隆輸入並在克隆之前調用val('')(調用jQuery $(input).val('')與調用input.value =''是不同的)。

    這種方法的問題是,例如,在IE中,該事件在清除文件輸入時被調用兩次,並且您必須謹慎釋放內存和對要替換的輸入的引用,同時保留未由插件設置的當前樣式和事件處理程序

  2. 第二個更好,但也有問題。 將輸入內容包裝在表單標簽中,然后調用表單的reset方法。

     input.wrap('<form>').parent('form').trigger('reset'); input.unwrap(); 

    檢查有關form標記的sintax 的文檔 ,您將看到以下報價

    注意:嚴格禁止在另一個表單中嵌套一個表單。 這樣做的行為可能無法預測,這取決於用戶使用的瀏覽器。

    其背后的主要原因是,您的插件可以應用於已經存在於表單中的輸入標簽,從而使您留下無效的html,因此您必須包裝該表單以調用reset方法並立即刪除此表單。 還請記住,如果不使用表單,可能會對表單應用視覺樣式,從而破壞用戶界面。

第二種方法更容易修復您的代碼。 只需像這樣更改完整的回調。 在這種情況下,無需克隆。

complete: function () {
    defaults.onFinish.call(this);
    $this.wrap('<form>').parent('form').trigger('reset');
    $this.unwrap();
}

這種更改應該發生得如此之快,以使用戶不會注意到它們。 我測試了周圍的1000個元素,沒有可見的毛刺。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM