Очищення <type type = 'file' /> за допомогою jQuery


Відповіді:


529

Легко: ви обмотуєте <form>елемент, обнуляєте виклик у формі, а потім видаляєте форму за допомогою .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>запуску подання.


EDIT

Не працює в IE 11 через нефіксовану помилку. Текст (назва файлу) видаляється на вході, але його Fileсписок залишається заповненим.


14
Переможець! Працює у кожному браузері і уникає клонування поля введення. Але якщо кнопки очищення всередині форми, перейменуйте reset()їх, наприклад, на reset2(), тому що принаймні в Chrome усі поля очищені, якщо вони є reset(). І додайте event.preventDefault () після очищення дзвінка, щоб запобігти надсиланню. Таким чином: <button onclick="reset2($('#file'));event.preventDefault()">Reset file</button>. Приклад роботи: jsfiddle.net/rPaZQ/23 .
Timo Kähkönen

28
Проблема в тому, що це принаймні тимчасово робить документ недійсним. (Форми не можуть містити інших форм.) Працює вона в даний час чи ні, її можна вільно зламати будь-коли.
cHao

6
@cHao, звичайно, це справедливо лише в тому випадку, якщо вхідний елемент насправді є такою формою, якою він не повинен бути.
Ninjakannon

7
Що стосується наявності форми у формі, ви завжди можете створити новий елемент форми поза DOM або додати його до тіла, якщо хочете, а потім перемістити вхідний елемент всередину цієї форми. Потім ви скинете цю нову форму, перемістіть вхідний елемент туди, де він був, і видаліть додатковий елемент форми.
Кевін Гайдт

4
Щойно я виявив, що це не працює в IE 11. Ми використовуємо PixelFileInput - який використовує такий підхід. І поки текст і мініатюра очищаються, список файлів об’єкта залишається тим самим :(
Ian Grainger

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

Fiddle: http://jsfiddle.net/jonathansampson/dAQVM/

Якщо клонування, зберігаючи обробники подій, представляє будь-які проблеми, які ви могли б розглянути, як використовувати делегування події для обробки кліків на цьому елементі управління з батьківського елемента:

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

Це запобігає необхідності клонування будь-яких обробників разом з елементом під час оновлення елемента керування.


50
Ви також можете використовувати метод .clone () у полі $ ('# clone'). SubstituWith ($ (this) .clone ());
metric152

4
Він просто нічого не робить - помилок у firebug немає. Мені довелося додати control.val (''); щоб очистити вікно введення файлу. Ваш код працював у chrome і ie9, як ніби.
mnsr

10
Це все ще не працює. Його потрібно очистити перед заміною. Тому ви хочете .val () раніше .replaceWith (). Отже, це буде control.val (''). SubstituWith (...);
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

Ви не можете отримати приєднаний обробник подій безпосередньо від самого елемента.

Ось загальний принцип у ванільному 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
gregor

2
Те саме рішення, що і вище
PhilT

2
Це неправильно, ми не можемо встановити поле заданому значенню, але, сподіваємось, ми зможемо його очистити.
fralbo

44

Це працює для мене.

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

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

Сподіваюся, це допомагає.


1
Для мене працює! Варто зазначити, що якщо у вас є будь-які слухачі подій, викликані зміною вхідного файлу, вам потрібно перепризначити їх, як тільки ви заміните вхід.
JCollerton

20

У IE8 вони зробили поле File File для читання лише для безпеки. Дивіться блог команди IE :

Історично склалося, що контроль над завантаженням файлів HTML () став джерелом значної кількості вразливостей щодо розкриття інформації. Для вирішення цих питань було внесено дві зміни у поведінку контролю.

Щоб заблокувати атаки, які покладаються на "крадіжку" натискань клавіш, щоб наказово ввести в оману користувача введення локального шляху файлу в елемент управління, поле редагування "Шлях файлу" тепер доступне лише для читання. Користувач повинен чітко вибрати файл для завантаження за допомогою діалогового вікна «Огляд файлів».

Крім того, для URLAction "Включити шлях до локального каталогу під час завантаження файлів" встановлено значення "Вимкнути" для Інтернет-зони. Ця зміна запобігає витоку потенційно чутливої ​​інформації локальної файлової системи в Інтернет. Наприклад, замість того, щоб подати повний шлях C: \ users \ ericlaw \ документи \ secret \ image.png, Internet Explorer 8 тепер подасть лише ім'я файлу image.png.


16

$("#control").val('')це все, що вам потрібно! Тестовано на Chrome за допомогою JQuery 1.11

Інші користувачі також пройшли тестування в Firefox.


2
Як пояснюється в багатьох інших публікаціях, це не є зручним для браузера.
Тиш

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

1
Помилка в Internet Explorer, оскільки файл типу вводу читається лише в IE>
Lucky,

4
Працює в хромі та 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). метод substituWith () працює в обох браузерах (хром, firefox)
Gaurav Sharma

Спочатку я повинен помітити, що "$ .browser видалено з jquery 1.9", але останні два рядки (Зміна атрибуту типу тексту та повернення його назад у файл) спрацювали. Додатково я спробував встановити $ ('# control'). Val (''); або в javascript document.getElementById (контроль) .value = ''; і працював теж, і не знаю, чому нам не слід використовувати цей підхід !? Нарешті я вирішив використати їх обох.
QMaster

8

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

Використання просте:

// Очистити всі файлові поля:
$ ("input: файл"). clearInputs ();

// Очистити також приховані поля:
$ ("input: файл"). clearInputs (true);

// Очистити конкретні поля:
$ ("# myfilefield1, # ​​myfilefield2"). чіткі входи ();
/ **
 * Очищає вибрані елементи форми.
 * /
$ .fn.clearFields = $ .fn.clearInputs = функція (includeHidden) {
    var re = / ^ (?: color | дата | datetime | email | місяць | номер | пароль | діапазон | пошук | tel | текст | час | url | тиждень) $ / i; // "прихованого" немає у цьому списку
    повернути this.each (function () {
        var t = this.type, tag = this.tagName.toLowerCase ();
        if (re.test (t) || тег == 'textarea') {
            this.value = '';
        }
        інакше, якщо (t == 'прапорець' || t == 'радіо') {
            this. prove = false;
        }
        інакше, якщо (tag == 'select') {
            this.selectedIndex = -1;
        }
        інакше, якщо (t == "файл") {
            якщо (/MSIE/.test(navigator.userAgent)) {
                $ (this) .replaceWith ($ (this) .clone (true));
            } else {
                $ (це) .val ('');
            }
        }
        інакше, якщо (включати прихований) {
            // includeHidden може бути значенням true, або це може бути рядком селектора
            // із зазначенням спеціального тесту; наприклад:
            // $ ('# myForm'). clearForm ('. спеціальний: приховано')
            // вищеописане очистить приховані входи, які мають клас "спеціальний"
            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
@Jonathan, працює і для мене, але якщо встановити його на що-небудь інше, це помилка безпеки. Випробувано на FF4.
Бренден

reset () - це власний метод JS, тому якщо ви виберете форму через jQuery, вам потрібно вийняти елемент із сфери jQuery. $ ("form # 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()Річ зовсім НЕ працює в Opera (і , можливо , інші). Він зберігає зміст.

Найближчим тут для мене був метод Джонатана, але я гарантував, що поле збереже своє ім'я, класи тощо, зроблені для безладного коду в моєму випадку.

Щось подібне може спрацювати добре (завдяки Квентіну теж):

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. Не забудьте використовувати делегування для будь-яких подій, які ви приєднали до елемента введення файлу, тому вони все ще працюють, коли зроблений клон.

Що я не розумію, це те, хто на землі думав, що не дозволяти вам очистити поле введення з недійсного неприйнятного вибору файлів було гарною ідеєю?

Гаразд, не дозволяйте мені динамічно встановлювати це значення, щоб я не міг вилучити файли з ОС користувача, але дозвольте очистити недійсний вибір без скидання всієї форми.

Це не так, як "прийміть" будь-що, крім фільтру, так і в IE10, він навіть не розуміє типи mime MS Word, це жарт!


Це майже працює. Єдине, що вам потрібно зробити, щоб зробити цю роботу в Firefox - це використовувати .pop()у масиві файлів, а не встановлювати її на нуль. це здається, щоб очистити файл належним чином.
kmacdonald

2

На моєму Firefox 40.0.3 працюю лише з цим

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

1
$ ('input [type = файл]'). substituWith ($ ('input [type = файл]'). clone (true) .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
Привіт Ніраж. Ласкаво просимо. Ця відповідь цілком може бути правильною, але вона може використовувати пояснення.
туманування

0

Це працює з Chrome, FF та Safari

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

Може не працювати з IE або Opera


1
Виглядає майже ідентично самій проблемі в ОП
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.