使用jQuery清除<input type ='file'/>


Answers:


529

简易:<form>将元素环绕起来,在表单上调用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所述,如果您有按钮来触发重置内部的字段,则<form>必须调用.preventDefault()该事件以防止<button>触发提交。


编辑

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


14
优胜者!在每种浏览器中均可使用,并避免克隆输入字段。但是,如果清除按钮位于表格内部,请重命名reset()为例如。reset2(),因为至少在Chrome中清除了所有字段(如果已清除)reset()。并在清除调用后添加event.preventDefault()以防止提交。这种方式:<button onclick="reset2($('#file'));event.preventDefault()">Reset file</button>。工作示例:jsfiddle.net/rPaZQ/23
TimoKähkönen2013年

28
问题是,这至少暂时使文档无效。(表单不能包含其他表单。)无论当前是否有效,都可以随时随意中断。
cHao 2013年

6
@cHao,当然,只有在输入元素实际上是某种形式(不一定是某种形式)时,这才成立。
Ninjakannon

7
关于在表单中包含表单,您总是可以在DOM外部创建一个新的form元素,或者根据需要将其附加到正文中,然后将input元素移动到该表单内部。然后,您将重置该新表单,将输入元素移回原来的位置,并删除其他表单元素。
凯文·海德

4
我刚刚发现这在IE 11中不起作用。我们使用的是PixelFileInput-使用这种方法。并且在清除了文本和缩略图的同时,对象的文件列表仍然相同:(
Ian Grainger

434

快速解答:更换它。

在下面的代码中,我使用replaceWithjQuery方法将控件替换为其自身的副本。如果您有任何绑定到此控件上事件的处理程序,我们也要保留这些处理程序。为此,我们将其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);

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


50
您还可以在$('#clone')。replaceWith($(this).clone())字段上使用.clone()方法。
metric152

4
它根本什么也没做-萤火虫没有错误。我必须添加control.val(''); 清除文件输入框。您的代码按原样在chrome和ie9中工作。
mnsr 2012年

10
它仍然不起作用。需要在更换之前将其清除。因此,您需要在.replaceWith()之前添加.val()。因此它将是control.val('')。replaceWith(...);
mnsr 2012年

6
我下面有个比这更干净的解决方案:stackoverflow.com/a/13351234/909944
2013年

2
由于历史原因,此答案在此处。现代浏览器支持input.value = null;
安德烈Werlang

113

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的差异足够大,以至于Java版本由于MS的使用方式不同而无法运行,那么我认为jquery方法应该为您处理它,否则值得将它与jquery团队一起向jquery团队指出。 IE所需的方法。(我看到有人说“这不适用于IE”,但没有任何普通的JavaScript来显示它如何在IE上起作用(应该是“安全功能”?),也许也将它报告为MS的错误(如果他们愿意的话)算一下),以便在任何较新的版本中得到修复)

就像在另一个答案中提到的,jquery论坛上的帖子

 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和其他库具有维护此类列表所需的所有其他支持方法,这只是一个演示。


这可行!(至少在这个答案的开头至少是香草JS位)。我已经在最新的Chrome,Firefox和IE(11)中对此进行了测试。
PhilT

4
我正要添加一些您的非常相同的答案,但主要是.val('')。这不仅比克隆上载元素或添加嵌套表单还要简单吗?+1。
Erenor Paz 2015年

3
.val("")谢谢您,第一个JQuery解决方案(使用)运行良好。比克隆输入并替换它要简单得多。
雨果·辛克

51

出于明显的安全原因,您无法设置文件输入的值,甚至不能设置为空字符串。

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

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

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


6
在IE中无法正常工作。视觉上重置了值,但el.value仍报告先前的版本。它有助于重置el.value,但仅限于IE10 +。jsfiddle.net/9uPh5/2
gregor

2
与上述相同的解决方案
PhilT 2015年

2
错了,我们不能将字段设置为给定值,但希望我们可以清除它。
fralbo


20

在IE8中,为了安全起见,他们将“文件上载”字段设为只读。参见IE团队博客文章

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

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

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


16

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

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


2
正如此处许多其他文章所解释的,这不是跨浏览器友好的。
Tisch

据我了解,这会在哪些浏览器中失败?
TheHamstring

1
在Internet Explorer中失败,因为IE>中的输入类型文件为只读>
幸运

4
适用于Chrome和Firefox。绰绰有余。
naimul64

12

我在这里遇到了所有选择。这是我制作的一个有效的技巧:

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

并且您可以使用类似以下代码的jQuery触发重置:

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

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


3
好的,但是它将清除整个表格。.不是特定的文件输入
Ashish Ratan

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)中均可使用
Gaurav Sharma

首先,我必须注意“ $ .browser已从jquery 1.9中删除”,但最后两行(将type属性更改为text,然后将其设置回该文件)起作用。另外我尝试设置$('#control')。val(''); 或在javascript document.getElementById(control).value =''; 并且也工作了,不知道为什么我们不应该使用这种方法!最后,我决定同时使用它们。
QMaster

8

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

用法很简单:

//清除所有文件字段:
$(“ input:file”)。clearInputs();

//清除隐藏的字段:
$(“ input:file”)。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();
        如果(re.test(t)||标签=='textarea'){
            this.value ='';
        }
        否则if(t =='checkbox'|| t =='radio'){
            this.checked = false;
        }
        否则if(tag =='select'){
            this.selectedIndex = -1;
        }
        否则,如果(t ==“文件”){
            如果(/MSIE/.test(navigator.userAgent)){
                $(this).replaceWith($(this).clone(true));
            }其他{
                $(this).val('');
            }
        }
        否则,如果(includeHidden){
            // includeHidden可以为true,也可以为选择器字符串
            //表示特殊测试;例如:
            // $('#myForm')。clearForm('。special:hidden')
            //上面的代码将清除具有“特殊”类的隐藏输入
            如果((includeHidden === true && /hidden/.test(t))||
                 (typeof includeHidden =='字符串'&& $(this).is(includeHidden)))
                this.value ='';
        }
    });
};

我不明白为什么这个答案不更支持?!
AlexB 2014年

1
@AlexB:因为,正如Timo解释的那样,仅清除一个文件输入字段是过大的。
TheCarver

不知道这样是否可行,但在FF 45.0.2上不再起作用:(
fralbo

5

文件输入的值是只读的(出于安全原因)。您不能以编程方式将其清空(除非调用窗体的reset()方法,该方法的作用域不仅限于该字段)。


16
我很困惑-我尝试了$(“#inputControl”)。val(“”),但确实确实使该字段为空。我想念什么吗?
桑普森2009年

1
@Jonathan也为我工作,但是如果将其设置为其他任何内容,则是安全错误。在FF4中测试。
布伦登

reset()是一种JS本机方法,因此,如果您通过jQuery选择表单,则需要将该元素移出jQuery范围。$(“ form#myForm”)[0] .reset();
克里斯·史蒂芬斯

4
@Jonathan它对您有用,因为您没有在IE中这样做。只有IE才能停止此安全问题。定期清除值器和Firefox的作品,而不是IE
VoidKing

5

我能够使用以下代码进行操作:

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

5

我一直在寻找清除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>


4

.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中,它似乎可以正常工作。我看不到它什么都不起作用的任何原因-表单上的reset选项已经存在了很长时间。
SpoonNZ

4

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

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。这似乎可以正确清除文件。
kmacdonald

2

在我的Firefox 40.0.3上仅与此兼容

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

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

2

它适用于所有浏览器。

        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);
        }

1

我尝试了用户提到的大多数技术,但是它们都不在所有浏览器中都有效。即: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);

0

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

1
嗨,Niraj。欢迎。这个答案很可能是正确的,但可以使用一些解释。
tomfanning 2012年

0

这适用于Chrome,FF和Safari

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

可能不适用于IE或Opera


1
看起来与OP中的问题几乎相同
Trindaz

1
不是ecmascript标准,出于安全原因,输入类型文件的值是保护属性。
e-info128 2013年

0

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

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

0
function clear() {
    var input = document.createElement("input");
    input.setAttribute('type', 'file');
    input.setAttribute('value', '');
    input.setAttribute('id', 'email_attach');

    $('#email_attach').replaceWith( input.cloneNode() );
}

0

它对我不起作用:

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

所以在ASP MVC中,我使用剃须刀功能来替换文件输入。首先,使用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>

0

一种简单的方法是更改​​输入类型,然后再次将其更改回。

像这样:

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

-1

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

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

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

但这也克隆了它的价值,所以您最好像这样

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

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

-4

这很简单(在所有浏览器中均可使用[歌剧除外]):

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

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


我不关心歌剧。只需将其包装在表格中即可,如果您需要的话。我个人不在乎,我会使用我的方法。
2012年

2
这根本不是一个很好的答案,但是主要的问题是态度真的很糟糕
Sam P

-5

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

document.onlyform.upload.value="";

假设上传是名称:

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

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

为我工作,我认为这更容易。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.