Обнаружение повторного выбора файла в input type=file

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы событие изменения срабатывало при выборе одного и того же файла, применяется элемент <input type="file">. Заключается это в обнулении значения этого поля ввода после выбора файла:

JS
Скопировать код
const inputFile = document.getElementById('fileInput');
inputFile.addEventListener('change', () => {
  // Здесь мы вставляем наш код...
  
  inputFile.value = ''; // *Всё легко*, словно и не было файла здесь
});

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

Кинга Идем в IT: пошаговый план для смены профессии

Когда требуется загружать один и тот же файл снова и снова...

Умение "доить" корову не однажды

Существует несколько способов для очистки значения поля ввода, которые эффективно работают как с применением различных библиотек, так и с чистым JavaScript:

JS
Скопировать код
// Чистый JavaScript
// Профессиональный совет: ни один фреймворк не был пострадан при написании этого кода.
inputFile.onclick = () => inputFile.value = '';

// jQuery
// jQuery зарекомендовал себя с лучшей стороны, несмотря на его возраст.
$('#fileInput').on('click', () => $('#fileInput').prop('value', ''));

// React
// Мы отдаем дань React.
const handleFileClick = (event) => {
  event.target.value = null;
  // Затем происходит перерисовка компонента после изменения состояния
}

.attr и .prop в jQuery: какая между ними разница?

В jQuery использование .prop('value', '') вместо .attr('value', '') обеспечивает более надёжные результаты. Это изменение влияет напрямую на свойство и обеспечивает большую стабильность:

JS
Скопировать код
// Включаем магию jQuery
$('#fileInput').on('click', () => $(this).prop('value', ''));

// Это может выглядеть невинно, но лучше не впадать в крайности
$('#fileInput').on('click', () => $(this).attr('value', ''));

jsFiddle как пространство для экспериментов

Ваш лабораторный стол для тестирования – это онлайн-редактор jsFiddle. Здесь вы можете на практике испытать представленные выше подходы. Все нововведения всего лишь в одном клике от вас.

Подготовка и предупреждения

Применяя этот метод, стоит помнить о нескольких важных моментах:

  • Осуществляйте тщательное тестирование в различных браузерах для обеспечения относительной независимости от различных платформ.
  • Тонко настраивайте обработку событий кликов, чтобы логически верный выбор файла был обеспечен.
  • Будьте готовы к тому, что ограничения, налагаемые браузерами с целью обеспечения безопасности, могут приводить к непредсказуемым последствиям.

Визуализация

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

Markdown
Скопировать код
📷🍎: Первый снимок яблока (первый выбор файла)
🔄🍎: Взгляните, яблоко снова упало (тот же файл выбран повторно)

Но если в коде прописано событие изменения, вы сможете отреагировать на каждое падение, даже если это – тот же самый объект:

JS
Скопировать код
document.getElementById('file-input').addEventListener('change', function() {
  this.value = null;
});
Markdown
Скопировать код
📷🍎🔽: Снова упало? (Изменение для одного и того же файла отслежено)

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

Мудрость TypeScript

Обеспечение типобезопасности с TypeScript

При использовании TypeScript не менее важным становится обеспечение типобезопасности при очистке значения поля ввода:

typescript
Скопировать код
const handleFileClick = (event: React.MouseEvent<HTMLInputElement>) => {
  const input = event.target as HTMLInputElement;
  // Теперь я спокоен, что input.value существует. Типобезопасность обеспечена.
  input.value = '';
};

Здесь мы уточняем, что event.target является HTMLInputElement, что позволит нам изменять input.value без риска для безопасности кода.

Дополнительные особые случаи, потому что жизнь полна сюрпризов

Случайные клики и неуверенные выборы

Если пользователь случайно кликнул на поле ввода, но затем отменил выбор файла, существенно важно убедиться в наличии выбранного файла:

JS
Скопировать код
inputFile.addEventListener('change', (event) => {
  if (!event.target?.files?.length) {
    // Здесь нету файлов...
    return;
  }
  
  // Логика обработки файла начинается здесь…
  event.target.value = null; // Производим сброс значения для нового выбора файла
});

Если пользователь выбирает тот же файл случайно

В приложениях, где нет необходимости в повторной загрузке того же файла, может потребоваться дополнительная логика для предотвращения случайного повторного выбора:

JS
Скопировать код
let lastFile;

inputFile.addEventListener('change', (event) => {
  const currentFile = event.target.files[0];
  
  if (currentFile === lastFile) {
    // О нет, файл выбран снова! Этого быть не должно.
    console.log('Обнаружен повторный выбор файла.');
    return;
  }
  
  lastFile = currentFile;
  // Продолжаем обработку файла
});

Полезные материалы

  1. Использование файлов в веб-приложениях – Веб-API | MDN – Познайте мир работы с файлами в веб-разработке.
  2. Событие "onchange" – Узнайте, в каких обстоятельствах событие "onchange" окажется полезным.
  3. HTML Стандарт – Изучайте стандарты, познайте правила и возможности использования поля ввода файла.
  4. HTMLElement: событие изменения – Веб-API | MDN – Глубоко изучите руководство по обработке событий изменения для HTML-элементов.