Borrar <input type = 'file' /> usando jQuery


Respuestas:


529

Fácil: envuelve un <form>elemento, llama a reset en el formulario y luego elimina el formulario usando .unwrap(). A diferencia de las .clone()soluciones en este hilo, terminas con el mismo elemento al final (incluidas las propiedades personalizadas que se establecieron en él).

Probado y trabajando en Opera, Firefox, Safari, Chrome e IE6 +. También funciona en otros tipos de elementos de formulario, con la excepción de 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

Como señala Timo a continuación, si tiene los botones para activar el restablecimiento del campo dentro del <form>, debe llamar .preventDefault()al evento para evitar que active <button>un envío.


EDITAR

No funciona en IE 11 debido a un error no corregido. El texto (nombre del archivo) se borra en la entrada, pero su Filelista permanece poblada.


14
¡Ganador! Funciona en todos los navegadores y evita la clonación de campos de entrada. Pero si los botones claros están dentro del formulario, cambie el nombre reset()a , por ejemplo. reset2(), porque al menos en Chrome todos los campos se borran si es así reset(). Y agregue event.preventDefault () después de borrar la llamada para evitar el envío. De esta manera: <button onclick="reset2($('#file'));event.preventDefault()">Reset file</button>. Ejemplo de trabajo: jsfiddle.net/rPaZQ/23 .
Timo Kähkönen

28
El problema es que esto al menos temporalmente invalida el documento. (Los formularios no pueden contener otras formas). Tanto si funciona actualmente como si no, es libre de romperse cuando lo desee.
cHao

66
@cHao, por supuesto, esto solo es cierto si el elemento de entrada está realmente en una forma, que no tiene que ser así.
Ninjakannon

77
Con respecto a tener un formulario dentro de un formulario, siempre puede crear un nuevo elemento de formulario fuera del DOM, o agregarlo al cuerpo si lo desea, luego mover el elemento de entrada al interior de ese formulario. Luego, restablecería ese nuevo formulario, movería el elemento de entrada a donde estaba y eliminaría el elemento de formulario adicional.
Kevin Heidt

44
Acabo de descubrir que esto no funciona en IE 11. Estamos utilizando PixelFileInput, que utiliza este enfoque. Y mientras se borra el texto y la miniatura, la lista de archivos del objeto permanece igual :(
Ian Grainger

434

Respuesta rápida: reemplácela.

En el siguiente código, uso el replaceWithmétodo jQuery para reemplazar el control con un clon de sí mismo. En el caso de que tenga algún controlador vinculado a eventos en este control, también queremos conservarlos. Para hacer esto pasamos truecomo el primer parámetro del clonemétodo.

<input type="file" id="control"/>
<button id="clear">Clear</button>
var control = $("#control");

$("#clear").on("click", function () {
    control.replaceWith( control = control.clone( true ) );
});

Violín: http://jsfiddle.net/jonathansampson/dAQVM/

Si la clonación, al tiempo que conserva los controladores de eventos, presenta algún problema que podría considerar usar la delegación de eventos para manejar los clics en este control desde un elemento primario:

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

Esto evita la necesidad de clonar cualquier controlador junto con el elemento cuando se actualiza el control.


50
También puede usar el método .clone () en el campo $ ('# clone'). ReplaceWith ($ (this) .clone ());
métrica152

44
Simplemente no hace nada, no hay error en firebug. Tuve que agregar control.val (''); para que borre el cuadro de entrada del archivo. Sin embargo, su código funcionó en Chrome y ie9 como está.
mnsr

10
Aún no funciona. Necesita ser limpiado antes del reemplazo. Por lo tanto, querrá .val () antes de .replaceWith (). Entonces sería control.val (''). ReplaceWith (...);
mnsr

66
Tengo una solución a continuación que es mucho más limpia que esta: stackoverflow.com/a/13351234/909944
slipheed

2
Esta respuesta está aquí por razones históricas. compatibilidad con navegadores modernosinput.value = null;
André Werlang

113

Se supone que Jquery se ocupará de los problemas del navegador cruzado / navegador anterior por usted.

Esto funciona en los navegadores modernos que probé: Chromium v25, Firefox v20, Opera v12.14

Usando jquery 1.9.1

HTML

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

Jquery

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

En jsfiddle

La siguiente solución de JavaScript también funcionó para mí en los navegadores mencionados anteriormente.

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

En jsfiddle

No tengo forma de probar con IE, pero en teoría esto debería funcionar. Si IE es lo suficientemente diferente como para que la versión de Javascript no funcione porque MS lo ha hecho de una manera diferente, el método jquery debería, en mi opinión, tratarlo por usted, de lo contrario valdría la pena señalarlo al equipo jquery junto con el método que requiere IE. (Veo a personas que dicen "esto no funcionará en IE", pero no hay Javascript vainilla para mostrar cómo funciona en IE (¿supuestamente una "característica de seguridad"?), Quizás también lo denuncien como un error a MS (si lo hicieran) contarlo como tal), para que se repare en cualquier versión más reciente)

Como se mencionó en otra respuesta, una publicación en el foro jquery

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

Pero jquery ahora ha eliminado la compatibilidad con las pruebas del navegador, jquery.browser.

Esta solución de JavaScript también funcionó para mí, es el equivalente a la vainilla del método jquery.replaceWith .

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

    fileopen.parentNode.replaceChild(clone, fileopen);
}, false);

En jsfiddle

Lo importante a tener en cuenta es que el método cloneNode no conserva los controladores de eventos asociados.

Ver este ejemplo.

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

En jsfiddle

Pero jquery.clone ofrece esto [* 1]

$("#fileopen").change(function () {
    alert("change");
});

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

    fileopen.replaceWith(clone);
});

En jsfiddle

[* 1] jquery puede hacer esto si los eventos se agregaron mediante los métodos de jquery, ya que mantiene una copia en jquery.data , de lo contrario no funciona, por lo que es un poco engañoso y evita que las cosas no funcionen compatible entre diferentes métodos o bibliotecas.

document.getElementById("fileopen").addEventListener("change", function () {
    alert("change");
}, false);

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

    fileopen.replaceWith(clone);
});

En jsfiddle

No puede obtener el controlador de eventos adjunto directamente desde el elemento mismo.

Aquí está el principio general en JavaScript de vainilla, así es como jquery y todas las demás bibliotecas lo hacen (aproximadamente).

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

En jsfiddle

Por supuesto, jquery y otras bibliotecas tienen todos los otros métodos de soporte necesarios para mantener dicha lista, esto es solo una demostración.


¡Esto funciona! (bueno, al menos el JS de vainilla al comienzo de esta respuesta). He probado esto en los últimos Chrome, Firefox e IE (11).
PhilT

44
Estaba a punto de agregar algunas de sus mismas respuestas, pero principalmente eso .val(''). ¿No es más simple que clonar el elemento de carga o agregar un formulario anidado? +1.
Erenor Paz

3
La primera solución JQuery (usando .val("")) funcionó perfectamente, gracias. Mucho más simple que clonar la entrada y reemplazarla también.
Hugo Zink

51

Por obvias razones de seguridad, no puede establecer el valor de una entrada de archivo, incluso en una cadena vacía.

Todo lo que tiene que hacer es restablecer el formulario donde está el campo o si solo desea restablecer la entrada del archivo de un formulario que contiene otros campos, use esto:

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

Aquí hay un ejemplo: http://jsfiddle.net/v2SZJ/1/


66
No funciona correctamente en IE. El valor visual se restablece, pero el.value aún informa la versión anterior. Ayuda a restablecer el el.value, pero solo en IE10 +. jsfiddle.net/9uPh5/2
gregor

2
Misma solución que la anterior
PhilT

2
Eso está mal, no podemos establecer el campo en un valor dado, pero con suerte, podemos borrarlo.
fralbo


20

En IE8, hicieron que el campo Carga de archivos fuera de solo lectura por seguridad. Vea la publicación del blog del equipo de IE :

Históricamente, el Control de carga de archivos HTML () ha sido la fuente de un número significativo de vulnerabilidades de divulgación de información. Para resolver estos problemas, se realizaron dos cambios en el comportamiento del control.

Para bloquear ataques que se basan en "robar" las teclas para engañar subrepticiamente al usuario para que escriba una ruta de archivo local en el control, el cuadro de edición Ruta de archivo ahora es de solo lectura. El usuario debe seleccionar explícitamente un archivo para cargar utilizando el cuadro de diálogo Explorar archivo.

Además, la acción URL "Incluir ruta de directorio local al cargar archivos" se ha establecido en "Desactivar" para la zona de Internet. Este cambio evita la filtración de información del sistema de archivos local potencialmente confidencial a Internet. Por ejemplo, en lugar de enviar la ruta completa C: \ users \ ericlaw \ documents \ secret \ image.png, Internet Explorer 8 ahora solo enviará el nombre de archivo image.png.


16

$("#control").val('')¡es todo lo que necesitas! Probado en Chrome con JQuery 1.11

Otros usuarios también han probado en Firefox.


2
Como muchas otras publicaciones aquí explican, esto no es compatible con el navegador cruzado.
Tisch

A mi entender, ¿en qué navegadores falla esto?
TheHamstring

1
Falla en Internet Explorer porque el archivo de tipo de entrada es de solo lectura en IE>
Lucky

44
Funciona en Chrome y Firefox. Mas que suficiente.
naimul64

12

Me quedé atrapado con todas las opciones aquí. Aquí hay un truco que hice que funcionó:

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

y puede activar el reinicio usando jQuery con un código similar a este:

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

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


3
ok, pero borrará todo el formulario ... entrada de archivo no específica
Ashish Ratan

8

Terminé con esto:

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

Puede que no sea la solución más elegante, pero funciona hasta donde puedo decir.



No funciona en Chrome 34 (Linux). El método replaceWith () funciona en ambos navegadores (Chrome, Firefox)
Gaurav Sharma

Al principio, debo notar "El $ .browser se ha eliminado de jquery 1.9", pero las dos últimas líneas (Cambiar el atributo de tipo a texto y luego volver a colocarlo en el archivo) funcionaron. Además intenté establecer $ ('# control'). Val (''); o en javascript document.getElementById (control) .value = ''; y funcionó también y no sé por qué no deberíamos usar este enfoque. Finalmente, decidí usar los dos.
QMaster

8

He usado https://github.com/malsup/form/blob/master/jquery.form.js , que tiene una función llamada clearInputs(), que es crossbrowser, bien probada, fácil de usar y maneja también problemas de IE y borrado de campos ocultos si es necesario. Tal vez sea una solución un poco larga para borrar solo la entrada de archivos, pero si se trata de cargas de archivos entre navegadores, se recomienda esta solución.

El uso es fácil:

// Borrar todos los campos del archivo:
$ ("input: file"). clearInputs ();

// Borrar también los campos ocultos:
$ ("input: file"). clearInputs (verdadero);

// Borrar campos específicos:
$ ("# myfilefield1, # ​​myfilefield2"). clearInputs ();
/ **
 * Borra los elementos de formulario seleccionados.
 * /
$ .fn.clearFields = $ .fn.clearInputs = function (includeHidden) {
    var re = / ^ (?: color | fecha | fecha y hora | correo electrónico | mes | número | contraseña | rango | búsqueda | tel | texto | hora | url | semana) $ / i; // 'oculto' no está en esta lista
    devuelve this.each (function () {
        var t = this.type, tag = this.tagName.toLowerCase ();
        if (re.test (t) || tag == 'textarea') {
            this.value = '';
        }
        si no (t == 'casilla de verificación' || t == 'radio') {
            this.checked = false;
        }
        si no (etiqueta == 'seleccionar') {
            this.selectedIndex = -1;
        }
        si no (t == "archivo") {
            if (/MSIE/.test(navigator.userAgent)) {
                $ (this) .replaceWith ($ (this) .clone (true));
            } más {
                $ (this) .val ('');
            }
        }
        más si (includeHidden) {
            // includeHidden puede ser el valor verdadero o puede ser una cadena de selección
            // indicando una prueba especial; por ejemplo:
            // $ ('# myForm'). clearForm ('. special: hidden')
            // lo anterior limpiaría las entradas ocultas que tienen la clase de 'especial'
            if ((includeHidden === true && /hidden/.test(t)) ||
                 (typeof includeHidden == 'string' && $ (this) .is (includeHidden)))
                this.value = '';
        }
    });
};

¡No entiendo por qué esta respuesta no está más votada?
AlexB

1
@AlexB: Porque, como explicó Timo, es excesivo borrar solo un campo de entrada de archivo.
TheCarver

No sé si eso funcionó, pero no más en FF 45.0.2 :(
fralbo

5

El valor de las entradas de archivo es de solo lectura (por razones de seguridad). No puede dejarlo en blanco mediante programación (aparte de llamar al método reset () del formulario, que tiene un alcance más amplio que solo ese campo).


16
Estoy confundido: probé $ ("# inputControl"). Val ("") y, de hecho, dejó el campo en blanco. ¿Me estoy perdiendo de algo?
Sampson

1
@ Jonathan, también funciona para mí, pero si lo configuras en otra cosa, es un error de seguridad. Probado en FF4.
Brenden el

reset () es un método nativo de JS, por lo que si selecciona el formulario a través de jQuery, debe sacar el elemento del alcance de jQuery. $ ("form # myForm") [0] .reset ();
Chris Stephens

44
@ Jonathan Funciona para ti porque no lo hiciste en IE. Este problema de seguridad es algo que solo IE detiene. Borrar el valor regularmente funciona tanto en Chrome como en Firefox, pero no en IE
VoidKing

5

Pude hacer que el mío funcionara con el siguiente código:

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

5

He estado buscando una forma simple y limpia de borrar la entrada de archivos HTML, las respuestas anteriores son geniales, pero ninguna de ellas responde realmente a lo que estoy buscando, hasta que encontré en la web una forma simple y elegante de hacerlo:

var $input = $("#control");

$input.replaceWith($input.val('').clone(true));

todo el crédito va a 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

La .clone()cosa no funciona en Opera (y posiblemente en otros). Mantiene el contenido.

El método más cercano aquí para mí fue el anterior de Jonathan, sin embargo, garantizar que el campo conservara su nombre, clases, etc., fue un código desordenado en mi caso.

Algo como esto podría funcionar bien (gracias a Quentin también):

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

¿Se ha probado esto en todos los principales navegadores?
Shawn

Parece funcionar bien en la última versión de Chrome / FF / Opera, y en IE8. No veo ninguna razón por la que no funcionaría en nada: la opción de restablecimiento en los formularios ha existido desde hace mucho tiempo.
SpoonNZ

4

He logrado que esto funcione usando lo siguiente ...

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

Esto ha sido probado en IE10, FF, Chrome y Opera.

Hay dos advertencias ...

  1. Todavía no funciona correctamente en FF, si actualiza la página, el elemento del archivo se vuelve a llenar con el archivo seleccionado. De dónde está obteniendo esta información está más allá de mí. ¿Qué más relacionado con un elemento de entrada de archivo podría intentar borrar?

  2. Recuerde usar la delegación en cualquier evento que haya adjuntado al elemento de entrada del archivo, para que sigan funcionando cuando se realice el clon.

Lo que no entiendo es quién pensó que no era una buena idea no permitirle borrar un campo de entrada de una selección de archivo inaceptable no válida.

OK, no me dejen configurarlo dinámicamente con un valor para que no pueda filtrar archivos del sistema operativo de un usuario, pero permítanme borrar una selección no válida sin restablecer un formulario completo.

De todos modos, no es que 'aceptar' haga otra cosa que un filtro y, en IE10, ni siquiera entiende los tipos mime de MS Word, ¡es una broma!


Esto casi funciona. Lo único que debe hacer para que esto funcione en Firefox es usarlo .pop()en la matriz de archivos en lugar de configurarlo como nulo. Esto parece borrar el archivo correctamente.
kmacdonald

2

En mi Firefox 40.0.3 solo funciona con esto

 $('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 el

2

Me funciona en todos los navegadores.

        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

Probé con la mayoría de las técnicas que mencionaron los usuarios, pero ninguna de ellas funcionó en todos los navegadores. es decir: clone () no funciona en FF para entradas de archivos. Terminé copiando manualmente la entrada del archivo, y luego reemplazando el original con el copiado. Funciona en todos los navegadores.

<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
Hola niraj Bienvenidos. Esta respuesta puede ser correcta, pero podría usar alguna explicación.
tomfanning

0

Esto funciona con Chrome, FF y Safari

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

Puede no funcionar con IE u Opera


1
Parece casi idéntico al problema en el OP
Trindaz

1
no es un estándar ecmascript, el valor del archivo de tipo de entrada es una propiedad de protección por razones de seguridad.
e-info128

0

Hágalo asíncrono y reinícielo después de que se hayan realizado las acciones deseadas del botón.

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

no me funciona

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

así que en asp mvc utilizo funciones de afeitar para reemplazar la entrada de archivos. primero cree una variable para la cadena de entrada con Id y Nombre y luego úsela para mostrar en la página y reemplazar al hacer clic en el botón de reinicio:

@{
    var attachmentInput = Html.TextBoxFor(c => c.Attachment, new { type = "file" });
}

@attachmentInput

<button type="button" onclick="$('#@(Html.IdFor(p => p.Attachment))').replaceWith('@(attachmentInput)');">--</button>

0

Una manera fácil es cambiar el tipo de entrada y volver a cambiarlo.

Algo como esto:

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

-1

Puedes reemplazarlo con su clon así

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

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

Pero esto clona con su valor también, así que será mejor que así

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

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

-4

Es fácil lol (funciona en todos los navegadores [excepto opera]):

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

JS Fiddle: http://jsfiddle.net/cw84x/1/


No podría importarme menos la ópera. Simplemente envuélvelo en el formulario y luego si te importa. Personalmente no me importa y usaré mi método.
Anónimo el

2
Esta no es una buena respuesta en absoluto, pero el problema principal fue la actitud realmente mala
Sam P

-5

¿Qué? En su función de validación, simplemente ponga

document.onlyform.upload.value="";

Suponiendo que cargar es el nombre:

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

Estoy usando JSP, no estoy seguro si eso hace la diferencia ...

Funciona para mí, y creo que es mucho más fácil.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.