【问题标题】:Clearing <input type='file' /> using jQuery使用 jQuery 清除 <input type='file' />
【发布时间】:2010-11-05 20:23:09
【问题描述】:

是否可以使用 jQuery 清除 &lt;input type='file' /&gt; 控件值?我尝试了以下方法:

$('#control').attr({ value: '' }); 

但它不起作用。

【问题讨论】:

    标签: javascript jquery html file-io forms


    【解决方案1】:

    快速回答:替换它。

    在下面的代码中,我使用replaceWith jQuery 方法将控件替换为自身的克隆。如果您有任何处理程序绑定到此控件上的事件,我们也希望保留这些处理程序。为此,我们传入true 作为clone 方法的第一个参数。

    <input type="file" id="control"/>
    <button id="clear">Clear</button>
    
    var control = $("#control");
    
    $("#clear").on("click", function () {
        control.replaceWith( control = control.clone( true ) );
    });
    

    小提琴:http://jsfiddle.net/jonathansampson/dAQVM/

    如果克隆在保留事件处理程序的同时会出现任何问题,您可以考虑使用事件委托来处理来自父元素的对此控件的点击:

    $("form").on("focus", "#control", doStuff);
    

    这样可以避免在刷新控件时将任何处理程序与元素一起克隆。

    【讨论】:

    • 这个解决方案的恼人之处在于你的代码中必须有两次元素,所以如果有人更改,例如名称,你必须更改你的代码两次(这很容易忘记)
    • 也可以在字段$('#clone').replaceWith($(this).clone());上使用.clone()方法;
    • 还是不行。更换前需要清除。因此,您需要在 .replaceWith() 之前使用 .val()。所以应该是 control.val('').replaceWith(...);
    【解决方案2】:

    文件输入的值是只读的(出于安全原因)。您不能以编程方式将其置空(除了调用表单的 reset() 方法,它的范围比该字段更广泛)。

    【讨论】:

    • 我很困惑 - 我尝试了 $("#inputControl").val("") 并且它确实使该字段空白。我错过了什么吗?
    • @Jonathan,也适用于我,但如果您将其设置为其他任何内容,则会出现安全错误。在 FF4 中测试。
    • reset() 是一种 JS 原生方法,因此如果您通过 jQuery 选择表单,则需要将元素移出 jQuery 范围。 $("form#myForm")[0].reset();
    • @Jonathan 它对你有用,因为你没有在 IE 中这样做。这个安全问题只有 IE 才会停止。定期清除值在 Chrome 和 Firefox 中都有效,但在 IE 中无效
    【解决方案3】:

    在 IE8 中,为了安全起见,他们将文件上传字段设为只读。见IE team blog post

    从历史上看,HTML 文件上传控件 () 一直是大量信息泄露漏洞的来源。为了解决这些问题,对控件的行为进行了两项更改。

    为了阻止依靠“窃取”击键来暗中诱骗用户在控件中键入本地文件路径的攻击,文件路径编辑框现在是只读的。用户必须使用“文件浏览”对话框明确选择要上传的文件。

    此外,“上传文件时包括本地目录路径”URLAction 已针对 Internet 区域设置为“禁用”。此更改可防止潜在敏感的本地文件系统信息泄露到 Internet。例如,Internet Explorer 8 现在将仅提交文件名 image.png,而不是提交完整路径 C:\users\ericlaw\documents\secret\image.png。

    【讨论】:

      【解决方案4】:

      什么? 在您的验证功能中,只需输入

      document.onlyform.upload.value="";
      

      假设上传的是名字:

      <input type="file" name="upload" id="csv_doc"/>
      

      我正在使用 JSP,不确定这是否会有所不同...

      对我有用,而且我认为它更容易。

      【讨论】:

        【解决方案5】:

        $("input[type=file]").wrap("<div id='fileWrapper'/>");
        $("#fileWrapper").append("<div id='duplicateFile'   style='display:none'>"+$("#fileWrapper").html()+"</div>");
        $("#fileWrapper").html($("#duplicateFile").html());
        

        【讨论】:

        • 嗨尼拉吉。欢迎。这个答案很可能是正确的,但它可以使用一些解释。
        【解决方案6】:

        这适用于 Chrome、FF 和 Safari

        $("#control").val("")
        

        可能不适用于 IE 或 Opera

        【讨论】:

        • 看起来几乎与 OP 中的问题完全相同
        • 不是 ecmascript 标准,输入类型文件的值是出于安全原因的保护属性。
        【解决方案7】:

        很容易哈哈(适用于所有浏览器[除了歌剧]):

        $('input[type=file]').each(function(){
            $(this).after($(this).clone(true)).remove();
        });
        

        JS 小提琴:http://jsfiddle.net/cw84x/1/

        【讨论】:

        • 我对歌剧一点也不在乎。如果你在乎,只需将其包装在表格中即可。我个人不在乎,我会用我的方法。
        • 这根本不是一个好的答案,但主要问题是态度非常糟糕
        【解决方案8】:

        我最终得到了这个:

        if($.browser.msie || $.browser.webkit){
          // doesn't work with opera and FF
          $(this).after($(this).clone(true)).remove();  
        }else{
          this.setAttribute('type', 'text');
          this.setAttribute('type', 'file'); 
        }
        

        可能不是最优雅的解决方案,但据我所知,它确实有效。

        【讨论】:

        • 在 chrome 34 (linux) 中不起作用。 replaceWith() 方法适用于两种浏览器(chrome、firefox)
        • 首先我必须注意到“$.browser 已从 jquery 1.9 中删除”但最后两行(将类型属性更改为文本,然后将其设置回文件)有效。另外我尝试设置 $('#control').val('');或在 javascript document.getElementById(control).value = '';并且也工作过,不知道为什么我们不应该使用这种方法!?最后,我决定同时使用它们。
        【解决方案9】:

        .clone() 的东西在 Opera(可能还有其他)中工作。它保留内容。

        对我来说最接近的方法是 Jonathan 的早期方法,但在我的情况下,确保字段保留其名称、类等会导致代码混乱。

        这样的事情可能会很好用(也感谢 Quentin):

        function clearInput($source) {
            var $form = $('<form>')
            var $targ = $source.clone().appendTo($form)
            $form[0].reset()
            $source.replaceWith($targ)
        }
        

        【讨论】:

        • 这在所有主流浏览器中都经过测试了吗?
        • 它似乎在最新版本的 Chrome/FF/Opera 和 IE8 中运行良好。我看不出它在任何事情上都不起作用的任何原因 - 表单上的重置选项已经存在了很长时间。
        【解决方案10】:

        简单:您将&lt;form&gt; 包裹在元素周围,在表单上调用reset,然后使用.unwrap() 删除表单。与此线程中的 .clone() 解决方案不同,您最终会得到相同的元素(包括在其上设置的自定义属性)。

        在 Opera、Firefox、Safari、Chrome 和 IE6+ 中测试和工作。也适用于其他类型的表单元素,type="hidden" 除外。

        window.reset = function(e) {
          e.wrap('<form>').closest('form').get(0).reset();
          e.unwrap();
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        
        <form>
          <input id="file" type="file">
          <br>
          <input id="text" type="text" value="Original">
        </form>
        
        <button onclick="reset($('#file'))">Reset file</button>
        <button onclick="reset($('#text'))">Reset text</button>

        JSFiddle

        正如 Timo 在下面指出的,如果您有用于触发 &lt;form&gt; 内的字段重置的按钮,则必须在事件上调用 .preventDefault() 以防止 &lt;button&gt; 触发提交。


        编辑

        由于未修复的错误,无法在 IE 11 中运行。输入中的文本(文件名)被清除,但其File 列表仍然填充。

        【讨论】:

        • 赢家!适用于所有浏览器并避免克隆输入字段。但如果清除按钮在表单内,请将reset() 重命名为例如。 reset2(),因为至少在 Chrome 中,如果是 reset(),所有字段都会被清除。并在清除调用后添加 event.preventDefault() 以防止提交。这样:&lt;button onclick="reset2($('#file'));event.preventDefault()"&gt;Reset file&lt;/button&gt;。工作示例:jsfiddle.net/rPaZQ/23.
        • @Timo,我已将该函数重命名为 resetFormElement 并添加了一条注释,说明您应该在按钮 onclick 上防止Default()。
        • 问题是,这至少暂时使文档无效。 (表单不能包含其他表单。)无论当前是否有效,它都可以随时随意中断。
        • @cHao,当然,这只有在输入元素实际上是一个表单时才是正确的,它不一定是。
        • 最新的 Chrome 不喜欢它(get(0) 未定义),我不得不做.wrap('&lt;form&gt;&lt;/form&gt;'),无论如何都按照 jQuery 文档的建议。
        【解决方案11】:

        我使用过https://github.com/malsup/form/blob/master/jquery.form.js,它有一个名为clearInputs() 的函数,它是跨浏览器,经过良好测试,易于使用,还可以处理IE 问题和需要时清除隐藏字段。可能只清除文件输入的解决方案有点长,但是如果您正在处理跨浏览器文件上传,那么建议使用此解决方案。

        使用简单:

        // 清除所有文件字段: $("输入:文件").clearInputs(); // 清除隐藏字段: $("输入:文件").clearInputs(true); // 清除特定字段: $("#myfilefield1,#myfilefield2").clearInputs(); /** * 清除选中的表单元素。 */ $.fn.clearFields = $.fn.clearInputs = function(includeHidden) { var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' 不在此列表中 返回 this.each(function() { var t = this.type, tag = this.tagName.toLowerCase(); if (re.test(t) || tag == 'textarea') { this.value = ''; } else if (t == 'checkbox' || t == 'radio') { this.checked = false; } 否则 if (tag == 'select') { this.selectedIndex = -1; } 否则如果(t ==“文件”){ if (/MSIE/.test(navigator.userAgent)) { $(this).replaceWith($(this).clone(true)); } 别的 { $(this).val(''); } } 否则如果(包括隐藏){ // includeHidden 可以是真值,也可以是选择器字符串 // 表示特殊测试;例如: // $('#myForm').clearForm('.special:hidden') // 以上将清除具有“特殊”类的隐藏输入 if ( (includeHidden === true && /hidden/.test(t)) || (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) this.value = ''; } }); };

        【讨论】:

        • 我不明白为什么这个答案没有得到更多支持?!
        • @AlexB:因为,正如 Timo 所解释的那样,只清除一个文件输入字段就太过分了。
        • 不知道这是否有效,但在 FF 45.0.2 上不再有效:​​(
        【解决方案12】:

        使其异步,并在完成按钮所需的操作后将其重置。

            <!-- Html Markup --->
            <input id="btn" type="file" value="Button" onchange="function()" />
        
            <script>
            //Function
            function function(e) {
        
                //input your coding here           
        
                //Reset
                var controlInput = $("#btn");
                controlInput.replaceWith(controlInput = controlInput.val('').clone(true));
            } 
            </script>
        

        【讨论】:

          【解决方案13】:

          这对我有用。

          $("#file").replaceWith($("#file").clone());
          

          http://forum.jquery.com/topic/how-to-clear-a-file-input-in-ie

          希望对你有帮助。

          【讨论】:

          • 为我工作!值得注意的是,如果您有任何由文件输入更改触发的事件侦听器,那么您需要在替换输入后重新分配它们。
          【解决方案14】:

          Jquery 应该为您处理跨浏览器/旧浏览器的问题。

          这适用于我测试过的现代浏览器:Chromium v​​25、Firefox v20、Opera v12.14

          使用 jquery 1.9.1

          HTML

          <input id="fileopen" type="file" value="" />
          <button id="clear">Clear</button>
          

          jQuery

          $("#clear").click(function () {
              $("#fileopen").val("");
          });
          

          开启jsfiddle

          以下 javascript 解决方案也适用于上述浏览器。

          document.getElementById("clear").addEventListener("click", function () {
              document.getElementById("fileopen").value = "";
          }, false);
          

          开启jsfiddle

          我无法使用 IE 进行测试,但理论上应该可以。如果 IE 足够不同以至于 Javascript 版本无法工作,因为 MS 以不同的方式完成了它,我认为 jquery 方法应该为您处理它,否则值得将它与 jquery 团队一起指出IE 需要的方法。 (我看到人们说“这在 IE 上不起作用”,但没有香草 javascript 来展示它如何在 IE 上工作(据说是“安全功能”?),也许也将它作为错误报告给 MS(如果他们愿意这样算),以便在任何新版本中得到修复)

          就像另一个答案中提到的那样,jquery forum 上的帖子

           if ($.browser.msie) {
                $('#file').replaceWith($('#file').clone());
           } else {
                $('#file').val('');
           }
          

          但是 jquery 现在已经取消了对浏览器测试的支持,jquery.browser.

          这个 javascript 解决方案也适用于我,它是 jquery.replaceWith 方法的原版等价物。

          document.getElementById("clear").addEventListener("click", function () {
              var fileopen = document.getElementById("fileopen"),
                  clone = fileopen.cloneNode(true);
          
              fileopen.parentNode.replaceChild(clone, fileopen);
          }, false);
          

          开启jsfiddle

          需要注意的重要一点是cloneNode 方法不保留关联的事件处理程序。

          看这个例子。

          document.getElementById("fileopen").addEventListener("change", function () {
              alert("change");
          }, false);
          
          document.getElementById("clear").addEventListener("click", function () {
              var fileopen = document.getElementById("fileopen"),
                  clone = fileopen.cloneNode(true);
          
              fileopen.parentNode.replaceChild(clone, fileopen);
          }, false);
          

          开启jsfiddle

          但是jquery.clone 提供了这个[*1]

          $("#fileopen").change(function () {
              alert("change");
          });
          
          $("#clear").click(function () {
              var fileopen = $("#fileopen"),
                  clone = fileopen.clone(true);
          
              fileopen.replaceWith(clone);
          });
          

          开启jsfiddle

          [*1] 如果事件是由 jquery 的方法添加的,jquery 能够做到这一点,因为它在jquery.data 中保留一个副本,否则它不起作用,所以它有点作弊/解决方法,意味着不同的方法或库之间不兼容。

          document.getElementById("fileopen").addEventListener("change", function () {
              alert("change");
          }, false);
          
          $("#clear").click(function () {
              var fileopen = $("#fileopen"),
                  clone = fileopen.clone(true);
          
              fileopen.replaceWith(clone);
          });
          

          开启jsfiddle

          您不能直接从元素本身获取附加的事件处理程序。

          这是原版 javascript 的一般原则,这就是 jquery 和所有其他库的做法(大致)。

          (function () {
              var listeners = [];
          
              function getListeners(node) {
                  var length = listeners.length,
                      i = 0,
                      result = [],
                      listener;
          
                  while (i < length) {
                      listener = listeners[i];
                      if (listener.node === node) {
                          result.push(listener);
                      }
          
                      i += 1;
                  }
          
                  return result;
              }
          
              function addEventListener(node, type, handler) {
                  listeners.push({
                      "node": node,
                          "type": type,
                          "handler": handler
                  });
          
                  node.addEventListener(type, handler, false);
              }
          
              function cloneNode(node, deep, withEvents) {
                  var clone = node.cloneNode(deep),
                      attached,
                      length,
                      evt,
                      i = 0;
          
                  if (withEvents) {
                      attached = getListeners(node);
                      if (attached) {
                          length = attached.length;
                          while (i < length) {
                              evt = attached[i];
                              addEventListener(clone, evt.type, evt.handler);
          
                              i += 1;
                          }
                      }
                  }
          
                  return clone;
              }
          
              addEventListener(document.getElementById("fileopen"), "change", function () {
                  alert("change");
              });
          
              addEventListener(document.getElementById("clear"), "click", function () {
                  var fileopen = document.getElementById("fileopen"),
                      clone = cloneNode(fileopen, true, true);
          
                  fileopen.parentNode.replaceChild(clone, fileopen);
              });
          }());
          

          开启jsfiddle

          当然 jquery 和其他库都有维护这样一个列表所需的所有其他支持方法,这只是一个演示。

          【讨论】:

            【解决方案15】:

            出于明显的安全原因,您不能设置文件输入的值,即使是空字符串。

            您所要做的就是重置字段所在的表单,或者如果您只想重置包含其他字段的表单的文件输入,请使用:

            function reset_field (e) {
                e.wrap('<form>').parent('form').trigger('reset');
                e.unwrap();
            }​
            

            这里是一个例子:http://jsfiddle.net/v2SZJ/1/

            【讨论】:

              【解决方案16】:

              我尝试了用户提到的大多数技术,但它们都不能在所有浏览器中使用。即:clone() 在 FF 中不适用于文件输入。 我最终手动复制了文件输入,然后用复制的文件替换了原始文件。它适用于所有浏览器。

              <input type="file" id="fileID" class="aClass" name="aName"/>
              
              var $fileInput=$("#fileID");
              var $fileCopy=$("<input type='file' class='"+$fileInput.attr("class")+" id='fileID' name='"+$fileInput.attr("name")+"'/>");
              $fileInput.replaceWith($fileCopy);
              

              【讨论】:

                【解决方案17】:

                我被这里的所有选项卡住了。这是我制作的一个 hack:

                <form>
                 <input type="file">
                 <button type="reset" id="file_reset" style="display:none">
                </form>
                

                您可以使用 jQuery 触发重置,代码类似于:

                $('#file_reset').trigger('click');
                

                (jsfiddle:http://jsfiddle.net/eCbd6/)

                【讨论】:

                • 好的,但它会清除整个表单..不是特定的文件输入
                【解决方案18】:

                我能够让我使用以下代码:

                var input = $("#control");    
                input.replaceWith(input.val('').clone(true));
                

                【讨论】:

                  【解决方案19】:

                  我已经设法使用以下方法使其工作......

                  function resetFileElement(ele) 
                  {
                      ele.val(''); 
                      ele.wrap('<form>').parent('form').trigger('reset');   
                      ele.unwrap();
                      ele.prop('files')[0] = null;
                      ele.replaceWith(ele.clone());    
                  }
                  

                  已在 IE10、FF、Chrome 和 Opera 中测试。

                  有两个注意事项...

                  1. 在 FF 中仍然无法正常工作,如果刷新页面,文件元素会重新填充所选文件。从哪里获取这些信息超出了我的范围。我还可以尝试清除与文件输入元素相关的哪些内容?

                  2. 请记住对附加到文件输入元素的任何事件使用委托,以便在进行克隆时它们仍然有效。

                  我不明白,到底谁认为不允许您从无效的不可接受的文件选择中清除输入字段是个好主意?

                  好的,不要让我用值动态设置它,这样我就不能从用户的操作系统中提取文件,但是让我在不重置整个表单的情况下清除无效的选择。

                  无论如何,“接受”除了过滤器之外什么都不做,而且在 IE10 中,它甚至不理解 MS Word 的 mime 类型,这是个笑话!

                  【讨论】:

                  • 这几乎可以工作。要在 Firefox 中进行这项工作,您需要做的一件事是在文件数组上使用 .pop(),而不是将其设置为 null。这似乎可以正确清除文件。
                  【解决方案20】:

                  在我的 Firefox 40.0.3 上只能使用这个

                   $('input[type=file]').val('');
                   $('input[type=file]').replaceWith($('input[type=file]').clone(true));
                  

                  【讨论】:

                  • $('input[type=file]').replaceWith($('input[type=file]').clone(true).val(''));
                  【解决方案21】:

                  $("#control").val('') 就是你所需要的!使用 JQuery 1.11 在 Chrome 上测试

                  其他用户也在 Firefox 中进行了测试。

                  【讨论】:

                  • 正如这里的许多其他帖子所解释的,这不是跨浏览器友好的。
                  • 据我了解,这在哪些浏览器中会失败?
                  • 在 Internet Explorer 中失败,因为输入类型文件在 IE 中是只读的>
                  • 在 chrome 和 firefox 中工作。绰绰有余。
                  【解决方案22】:

                  它适用于所有浏览器。

                          var input = $(this);
                          var next = this.nextSibling;
                          var parent = input.parent();
                          var form = $("<form></form>");
                          form.append(input);
                          form[0].reset();
                          if (next) {
                              $(next).before(input);
                          } else {
                              parent.append(input);
                          }
                  

                  【讨论】:

                    【解决方案23】:

                    我一直在寻找简单而干净的方法来清除 HTML 文件输入,上面的答案很棒,但没有一个能真正回答我正在寻找的东西,直到我在网上遇到了一种简单而优雅的方法去做吧:

                    var $input = $("#control");
                    
                    $input.replaceWith($input.val('').clone(true));
                    

                    所有功劳归Chris Coyier

                    // Referneces
                    var control = $("#control"),
                        clearBn = $("#clear");
                    
                    // Setup the clear functionality
                    clearBn.on("click", function(){
                        control.replaceWith( control.val('').clone( true ) );
                    });
                    
                    // Some bound handlers to preserve when cloning
                    control.on({
                        change: function(){ console.log( "Changed" ) },
                         focus: function(){ console.log(  "Focus"  ) }
                    });
                    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
                    
                    <input type="file" id="control">
                    <br><br>
                    <a href="#" id="clear">Clear</a>

                    【讨论】:

                      【解决方案24】:

                      你可以像这样用它的克隆替换它

                      var clone = $('#control').clone();
                      
                      $('#control').replacewith(clone);
                      

                      但是这个克隆也有它的价值,所以你最好这样

                      var emtyValue = $('#control').val('');
                      var clone = emptyValue.clone();
                      
                      $('#control').replacewith(clone);
                      

                      【讨论】:

                        【解决方案25】:
                        function clear() {
                            var input = document.createElement("input");
                            input.setAttribute('type', 'file');
                            input.setAttribute('value', '');
                            input.setAttribute('id', 'email_attach');
                        
                            $('#email_attach').replaceWith( input.cloneNode() );
                        }
                        

                        【讨论】:

                          【解决方案26】:

                          它对我不起作用:

                          $('#Attachment').replaceWith($(this).clone());
                          or 
                          $('#Attachment').replaceWith($('#Attachment').clone());
                          

                          所以在 asp mvc 中我使用 razor 特性来替换文件输入。 首先为具有 Id 和 Name 的输入字符串创建一个变量,然后将其用于在页面中显示并在重置按钮单击时替换:

                          @{
                              var attachmentInput = Html.TextBoxFor(c => c.Attachment, new { type = "file" });
                          }
                          
                          @attachmentInput
                          
                          <button type="button" onclick="$('#@(Html.IdFor(p => p.Attachment))').replaceWith('@(attachmentInput)');">--</button>
                          

                          【讨论】:

                            【解决方案27】:

                            一种简单的方法是更改​​输入类型并再次更改。

                            类似这样的:

                            var input = $('#attachments');
                            input.prop('type', 'text');
                            input.prop('type', 'file')
                            

                            【讨论】:

                              猜你喜欢
                              • 2014-02-07
                              • 1970-01-01
                              • 1970-01-01
                              • 2011-09-06
                              • 2012-09-20
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多