Событие выбора файла ввода HTML не срабатывает при выборе того же файла


204

Есть ли шанс обнаружить каждый выбор файла, который пользователь сделал для HTML- элемента inputтипа file?

Это задавалось много раз, но обычно предлагаемое onchangeсобытие не срабатывает, если пользователь снова выбирает тот же файл.


7
Должен ли ваш код также запускаться, если пользователь нажимает кнопку Отмена? Можно ожидать, что нажатие кнопки «Отмена» ничего не даст, и я думаю, что большинство пользователей также ожидают, что повторный выбор того же файла будет иметь тот же эффект, что и «Отмена». Я не знаю, возможно ли это или нет, но я предлагаю вам все равно пересмотреть этот дизайн.
KRyan

1
При отмене он не должен срабатывать или обнаруживаться другим способом. Он больше предназначен для удаления комментария пользовательского интерфейса: если после выбора файла вызывается какое-либо действие, пользователь обычно ожидает, что действие повторится, если он снова выберет файл.
Дронус

Может быть, у нас может быть такое поведение, если мы установим inputзначение s в '' после того, как что-то сделаем с файлом. Но это также уберет видимое имя файла. Тем не менее, это может быть нормально, так как файл фактически обрабатывается, и результат этого действия может появиться где-то еще.
Дронус

Плз Объясни Que Что ты хочешь сделать?
Чемпион

1
Все, что я хочу, - это моделировать поведение настольных приложений старой школы. Если я снова «открываю» тот же файл в настольном приложении, он обычно перезагружается, или если с файлом выполняется какое-либо действие (например, преобразование его в другой формат), это действие выполняется снова. Это то, что пользователи настольных компьютеров могут ожидать и от веб-приложения, но событие fileввода onchangeне похоже.
Дронус

Ответы:


279

Установите значение inputдля nullкаждого onclickсобытия. Это сбросит inputзначение и вызовет onchangeсобытие, даже если выбран тот же путь.

input.onclick = function () {
    this.value = null;
};

input.onchange = function () {
    alert(this.value);
};​

Вот ДЕМО .

Примечание: это нормально, если ваш файл имеет префикс «C: \ fakepath \». Это функция безопасности, которая не позволяет JavaScript знать абсолютный путь к файлу. Браузер все еще знает это внутренне.


1
Я попробовал демо, но (используя Chrome 21) я продолжаю получать `C: \ fakepath` + затем имя файла, которое я выбрал (исключая путь). Предупреждение отображается при каждом выборе одного и того же файла.
Джаспер де Врис

1
@JasperdeVries Это функция безопасности, которая не позволяет JavaScript знать абсолютный путь к файлу. Браузер все еще знает путь внутри.
Брайан Устас

1
Кроме того, null является единственным допустимым значением для <input type = "file">. Так что если вы пытаетесь установить его как неопределенное и получаете исключение, то причина в этом.
Ноэль Абрахамс

5
Это не работает в IE11, если вы не сделаете небольшое изменение: демо .

21
Лучше поставить this.value = nullв конце, onchangeпотому что можно активировать элемент ввода, не нажимая на него (с помощью клавиатуры). Вы можете хранить, input.filesесли вам нужно сослаться на это позже.
Halcyon

24
<form enctype='multipart/form-data'>
    <input onchange="alert(this.value); this.value=null; return false;" type='file'>
    <br>
    <input type='submit' value='Upload'>
</form>

this.value=null; необходим только для Chrome, Firefox будет нормально работать только с return false;

Вот скрипка


2
просто и эффективно, только что протестировано в последних версиях IE и Chrome и работает как шарм. Спасибо за то, что поделились этим
Atul Chaudhary

8

В этой статье под заголовком «Использование ввода формы для выбора»

http://www.html5rocks.com/en/tutorials/file/dndfiles/

<input type="file" id="files" name="files[]" multiple />

<script>
function handleFileSelect(evt) {

    var files = evt.target.files; // FileList object

    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
     // Code to execute for every file selected
    }
    // Code to execute after that

}

document.getElementById('files').addEventListener('change', 
                                                  handleFileSelect, 
                                                  false);
</script>

Он добавляет прослушиватель событий в «change», но я протестировал его, и он срабатывает, даже если вы выбираете тот же файл, а не если вы отменяете.


Учитывая потенциально неоднозначное значение «изменения» в этом случае, вы пробовали это в нескольких браузерах? Возможно, вы захотите указать, какие из них вы попробовали, например, в Интернете, браузеры не всегда согласны с этими вещами.
Thor84no

2
Какую среду вы используете для своего теста? Мой опыт работы с Chrome был тем, который я указал в этом вопросе, changeсобытие будет происходить только при изменении имени файла.
Дронус

7

Используйте событие onClick для очистки значения целевого ввода, каждый раз, когда пользователь нажимает на поле. Это гарантирует, что событие onChange будет запущено и для того же файла. Работал для меня :)

onInputClick = (event) => {
    event.target.value = ''
}

<input type="file" onChange={onFileChanged} onClick={onInputClick} />

Использование TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}

Спасибо за решение.
Дипак Текчандани

1

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

   $('#myFile').change(function () {
       LoadFile("myFile");//function to do processing of file.
       $('#myFile').val('');// set the value to empty of myfile control.
    });

1
handleChange({target}) {
    const files = target.files
    target.value = ''
}

1
Эй, нгКурс! Ответы только на код могут решить проблему, но они гораздо полезнее, если вы объясните, как они решают эту проблему. Сообщество требует теории, а также кода, чтобы полностью понять ваш ответ.
RBT

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

1

Очистка значения 0-го индекса ввода работала для меня . Пожалуйста, попробуйте следующий код, надеюсь, это будет работать (AngularJs).

          scope.onClick = function() {
            input[0].value = "";
                input.click();
            };
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.