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

时间:2009-06-25 13:32:15

标签: javascript jquery html file-io html-form

是否可以使用jQuery清除<input type='file' />控件值?我尝试了以下内容:

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

但它不起作用。

27 个答案:

答案 0 :(得分:517)

简单:在元素周围包裹<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列表仍然填充。

答案 1 :(得分:430)

快速回答:替换它。

在下面的代码中,我使用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);

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

答案 2 :(得分:106)

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

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

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

答案 3 :(得分:48)

出于明显的安全原因,您无法设置文件输入的值,即使是空字符串也是如此。

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

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

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

答案 4 :(得分:43)

这对我有用。

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

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

希望它有所帮助。

答案 5 :(得分:20)

在IE8中,他们将“文件上载”字段设置为只读以确保安全性。请参阅IE team blog post

  

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

     

要阻止依赖“窃取”击键的攻击暗中欺骗用户输入控件的本地文件路径,文件路径编辑框现在是只读的。用户必须使用“文件浏览”对话框显式选择要上载的文件。

     

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

答案 6 :(得分: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/

答案 7 :(得分: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'); 
}

可能不是最优雅的解决方案,但据我所知,它可以正常工作。

答案 8 :(得分:8)

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

用法很简单:

// Clear all file fields:
$("input:file").clearInputs();

// Clear also hidden fields:
$("input:file").clearInputs(true);

// Clear specific fields:
$("#myfilefield1,#myfilefield2").clearInputs();
/**
 * Clears the selected form elements.
 */
$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
    return 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;
        }
        else if (tag == 'select') {
            this.selectedIndex = -1;
        }
        else if (t == "file") {
            if (/MSIE/.test(navigator.userAgent)) {
                $(this).replaceWith($(this).clone(true));
            } else {
                $(this).val('');
            }
        }
        else if (includeHidden) {
            // includeHidden can be the value true, or it can be a selector string
            // indicating a special test; for example:
            //  $('#myForm').clearForm('.special:hidden')
            // the above would clean hidden inputs that have the class of 'special'
            if ( (includeHidden === true && /hidden/.test(t)) ||
                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
                this.value = '';
        }
    });
};

答案 9 :(得分:5)

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

答案 10 :(得分: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>

答案 11 :(得分:5)

我能够使用以下代码:

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

答案 12 :(得分:4)

.clone()(或可能是其他人)中。它保留了内容。

这里最接近我的方法是Jonathan先前的方法,但确保该字段保留其名称,类等等,以便在我的案例中使用凌乱的代码。

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

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

答案 13 :(得分: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&amp;戏。

有两个警告......

  1. 在FF中仍然无法正常工作,如果刷新页面,则会使用所选文件重新填充文件元素。从哪里得到这些信息是超出我的。我可以尝试清除与文件输入元素相关的其他内容吗?

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

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

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

    它不像'accept'除了过滤器之外做任何其他事情而且在IE10中,它甚至不理解MS Word mime类型,这是一个笑话!

答案 14 :(得分:2)

在我的Firefox 40.0.3上只能使用此

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

答案 15 :(得分: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);
        }

答案 16 :(得分: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);

答案 17 :(得分: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>

答案 18 :(得分:0)


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

答案 19 :(得分: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() );
}

答案 20 :(得分: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>

答案 21 :(得分:0)

只需使用

 $("#fileUploaderID").val(''); 

答案 22 :(得分:0)

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

类似的事情:

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

答案 23 :(得分:-1)

适用于Chrome,FF和Safari

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

可能无法使用IE或Opera

答案 24 :(得分:-1)

您可以将其替换为其克隆

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

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

但是这个克隆的价值太高,所以你最好这样

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

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

答案 25 :(得分:-4)

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

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

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

答案 26 :(得分:-4)

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

即可
document.onlyform.upload.value="";

假设上传是名称:

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

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

适合我,我认为这样更容易。