Очистка <input type = 'file' /> с помощью jQuery


Ответы:


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

Как отмечает Тимо ниже, если у вас есть кнопки для запуска сброса поля внутри <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 .
Тимо Кяхконен

28
Проблема в том, что это по крайней мере временно делает документ недействительным. (Формы не могут содержать другие формы.) Работает ли она в настоящее время или нет, она может быть взломана в любое время.
cHao

6
@cHao, конечно, это верно только в том случае, если элемент ввода фактически находится в форме, которой он не должен быть.
Ниндзяканнон

7
Что касается наличия формы внутри формы, вы всегда можете создать новый элемент формы вне DOM или добавить его к телу, если хотите, а затем переместить элемент ввода внутрь этой формы. Затем вы должны сбросить эту новую форму, переместить элемент ввода обратно туда, где он был, и удалить дополнительный элемент формы.
Кевин Хейдт

4
Я только что обнаружил, что это не работает в IE 11. Мы используем PixelFileInput - который использует этот подход. И хотя текст и миниатюра очищены, список файлов объекта остается прежним :(
Ян Грейнджер,

434

Быстрый ответ: замени его.

В приведенном ниже коде я использую 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);

Это предотвращает необходимость клонирования любых обработчиков вместе с элементом при обновлении элемента управления.


50
Вы также можете использовать метод .clone () в поле $ ('# clone'). ReplaceWith ($ (this) .clone ());
metric152

4
Это просто ничего не делает - нет ошибки в firebug. Мне пришлось добавить control.val (''); чтобы очистить поле ввода файла. Ваш код работал в Chrome и ie9 как есть.
Mnsr

10
Это все еще не работает. Это должно быть очищено до замены. Так что вы хотели бы .val () перед .replaceWith (). Так что это будет control.val (''). ReplaceWith (...);
Mnsr

6
Ниже у меня есть решение, которое намного чище, чем это: stackoverflow.com/a/13351234/909944
slipheed

2
этот ответ здесь по историческим причинам. поддержка современных браузеровinput.value = null;
Андре Верланг

113

Предполагается, что Jquery позаботится о проблемах между браузерами и браузерами.

Это работает на современных браузерах, которые я тестировал: Chromium v25, 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

 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 и другие библиотеки имеют все другие методы поддержки, необходимые для поддержки такого списка, это просто демонстрация.


Это работает! (ну, по крайней мере, немного JS в начале этого ответа). Я проверял это в последних версиях Chrome, Firefox и IE (11).
PhilT

4
Я собирался добавить некоторые из тех же самых ответов, но в основном это .val(''). Разве это не проще, чем клонирование элемента загрузки или добавление вложенной формы? +1.
Эренор Пас

3
Первое решение JQuery (использование .val("")) работало отлично, спасибо. Намного проще, чем клонировать ввод и заменить его тоже.
Хьюго Цинк

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
Грегор

2
То же решение, что и выше
PhilT

2
Это неправильно, мы не можем установить поле на заданное значение, но, надеюсь, мы можем очистить его.
Fralbo

43

Это работает для меня.

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

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

Надеюсь, поможет.


1
Работает для меня! Стоит отметить, что если у вас есть какие-либо прослушиватели событий, вызванные изменением входного файла, вам необходимо переназначить их после замены ввода.
Дж. Коллертон

20

В IE8 они сделали поле загрузки файла доступным только для чтения для безопасности. Смотрите сообщение в блоге команды IE :

Исторически HTML Control Upload File () был источником значительного числа уязвимостей раскрытия информации. Чтобы решить эти проблемы, в поведение элемента управления были внесены два изменения.

Чтобы блокировать атаки, основанные на «краже» нажатий клавиш, чтобы тайно обмануть пользователя и ввести локальный путь к файлу в элемент управления, поле редактирования «Путь к файлу» теперь доступно только для чтения. Пользователь должен явно выбрать файл для загрузки с помощью диалога просмотра файлов.

Кроме того, для URLAction для параметра «Включить путь к локальному каталогу при загрузке файлов» было установлено значение «Отключить» для зоны Интернета. Это изменение предотвращает утечку потенциально важной информации локальной файловой системы в Интернет. Например, вместо того, чтобы указывать полный путь C: \ users \ ericlaw \ documents \ secret \ image.png, Internet Explorer 8 теперь будет отправлять только имя файла image.png.


16

$("#control").val('')это все, что тебе нужно! Протестировано на Chrome с использованием JQuery 1.11

Другие пользователи также протестировали в Firefox.


2
Как объясняют многие другие посты, это не подходит для разных браузеров.
Тиш

Насколько я понимаю, в каких браузерах это происходит?
TheHamstring

1
Сбои в Internet Explorer, поскольку файл входного типа доступен только для чтения в IE>
Lucky

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
хорошо, но он очистит всю форму .. не конкретный файл ввода
Ашиш Ратан

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», но две последние строки (изменение атрибута type на текст и затем возвращение его в файл) сработали. Кроме того, я попытался установить $ ('# control'). Val (''); или в javascript document.getElementById (control) .value = ''; и работал тоже, и не знаю, почему мы не должны использовать этот подход !? Наконец, я решил использовать их обоих.
QMaster

8

Я использовал https://github.com/malsup/form/blob/master/jquery.form.js , у которого есть вызываемая функция clearInputs(), которая является кроссбраузерной, хорошо протестирована, проста в использовании и обрабатывает также проблемы с IE и очистку скрытых полей. если нужно. Может быть, немного длинное решение, чтобы очистить только ввод файла, но если вы имеете дело с загрузкой файлов через браузер, то это решение рекомендуется.

Использование легко:

// Очистить все поля файла:
$ ( "Вход: файл") clearInputs ();.

// Очистить также скрытые поля:
$ ( "Входной файл":) clearInputs (истина);.

// Очистить определенные поля:
$ ( "# Myfilefield1, # ​​myfilefield2") clearInputs ().
/ **
 * Очищает выбранные элементы формы.
 * /
$ .fn.clearFields = $ .fn.clearInputs = function (includeHidden) {
    var re = / ^ (?: цвет | дата | дата / время | электронная почта | месяц | номер | пароль | диапазон | поиск | тел. | текст | время | url | неделя) $ / i; // скрытого нет в этом списке
    вернуть this.each (function () {
        var t = this.type, tag = this.tagName.toLowerCase ();
        if (re.test (t) || tag == 'textarea') {
            this.value = '';
        }
        иначе если (t == 'checkbox' || t == 'radio') {
            this.checked = false;
        }
        еще если (tag == 'select') {
            this.selectedIndex = -1;
        }
        иначе если (t == "файл") {
            if (/MSIE/.test(navigator.userAgent)) {
                $ (Это) .replaceWith ($ (это) .clone (истина));
            } еще {
                $ (Это) .val ( '');
            }
        }
        еще если (includeHidden) {
            // includeHidden может быть значением true или строкой селектора
            // указание специального теста; например:
            // $ ('# myForm'). clearForm ('. special: hidden')
            // выше будет очищать скрытые входы, которые имеют класс 'special'
            if ((includeHidden === true && /hidden/.test(t)) ||
                 (typeof includeHidden == 'string' && $ (this) .is (includeHidden)))
                this.value = '';
        }
    });
};

Я не понимаю, почему этот ответ не более проголосовал ?!
AlexB

1
@AlexB: Потому что, как объяснил Тимо, просто очищать одно поле ввода файла.
TheCarver

Не знаю, сработало ли это, но не больше на FF 45.0.2 :(
fralbo

5

Значение файловых входов доступно только для чтения (по соображениям безопасности). Вы не можете очистить его программно (кроме вызова метода reset () формы, которая имеет более широкую область действия, чем просто это поле).


16
Я в замешательстве - я попытался $ ("# inputControl"). Val (""), и это действительно пустое поле. Я что-то пропустил?
Сэмпсон

1
@ Джонатан, у меня тоже работает, но если вы установите его на что-то другое, это ошибка безопасности. Проверено в FF4.
Бренден,

reset () - это собственный метод JS, поэтому, если вы выбираете форму через jQuery, вам нужно вывести элемент из области видимости jQuery. $ ( "форма # MyForm") [0] .RESET ();
Крис Стивенс

4
@Jonathan Это работает для вас, потому что вы не делали этого в IE. Эта проблема безопасности - то, что только IE останавливает. Очистка значения регулярно работает как в Chrome, так и в Firefox, но не в IE
VoidKing

5

Я смог заставить мой работать со следующим кодом:

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

5

Я искал простой и понятный способ очистки ввода HTML-файла, приведенные выше ответы великолепны, но ни один из них действительно не отвечает на то, что я ищу, пока я не наткнулся в Интернете на простой и элегантный способ сделать это:

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

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

все дело в Крисе Койере .

// 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()вещь не работает в Опере (и, возможно, другие). Содержит содержание.

Самым близким методом для меня здесь был ранее Джонатан, однако в моем случае было гарантировано, что поле сохранило свое имя, классы и т. Д. Для грязного кода.

Примерно так может сработать (спасибо Квентину тоже):

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

Это было проверено во всех основных браузерах?
Шон

Похоже, что он отлично работает в последней версии Chrome / FF / Opera и IE8. Я не вижу никакой причины, по которой это не будет работать ни с чем - опция сброса в формах существует уже давно.
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. Не забудьте использовать делегирование для любых событий, которые вы прикрепили к элементу ввода файла, чтобы они работали даже после создания клона.

Что я не понимаю, так это то, что кто-то подумал, что не позволяя вам очистить поле ввода от недопустимого недопустимого выбора файла, было хорошей идеей?

Хорошо, не позволяйте мне динамически устанавливать его со значением, чтобы я не мог вытащить файлы из ОС пользователя, но позвольте мне очистить неправильный выбор без сброса всей формы.

Это не значит, что 'accept' делает что-либо, кроме фильтра, в любом случае, а в IE10 он даже не понимает типы пантомимы MS Word, это шутка!


Это почти работает. Единственное, что вам нужно сделать, чтобы заставить эту работу работать в Firefox, - это использовать .pop()массив файлов вместо того, чтобы устанавливать его в null. похоже, это правильно очищает файл.
kmacdonald

2

На моем Firefox 40.0.3 работает только с этим

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

1
. $ ( 'ввода [тип = файл]') ReplaceWith (. $ ( 'ввода [тип = файл]') клон (истина) .val ( ''));
Андрей

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
Привет, Нирадж. Добро пожаловать. Этот ответ вполне может быть правильным, но он может использовать некоторые объяснения.
Tomfanning

0

Это работает с Chrome, FF и Safari

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

Может не работать с IE или Opera


1
Выглядит почти идентично самой проблеме в OP
Trindaz

1
не является стандартом ecmascript, значение входного типа файла является свойством защиты по соображениям безопасности.
e-info128

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

Это легко, lol (работает во всех браузерах [кроме оперы]):

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

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


Мне наплевать на оперу. Просто оберните его в форму, если вам все равно. Мне лично все равно, и я буду использовать свой метод.
Аноним

2
Это не очень хороший ответ, но главной проблемой было действительно плохое отношение
Сэм Р

-5

Какая? В вашей функции проверки просто поместите

document.onlyform.upload.value="";

Предполагается, что загрузка это имя:

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

Я использую JSP, не уверен, что это имеет значение ...

У меня работает, и я думаю, что это намного проще.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.