JavaScript | Как получить список имён файлов на клиенте? — efim360.ru

JavaScript | Как получить список имён файлов на клиенте?

Задача

У нас есть файлы на компьютере (или ноутбуке). Мы хотим при помощи браузера получить список имён выбранных файлов из какой-нибудь директории на нашем компьютере (то есть на клиентской стороне, а не на серверной). Мы как бы хотим провзаимодействовать с этими файлами в будущем.

Как это сделать и с чего начать?

Шаг первый - Стандарт HTML и элемент input

На вкладках браузера мы всегда имеем дело с языком разметки HTML. У HTML есть много элементов, но нас будет интересовать всего один - это элемент ввода input.

Он может владеть всеми глобальными атрибутами языка HTML, а также имеет 32 своих собственных атрибутов.

HTML элемент input - Атрибуты содержимого - 2021
HTML элемент input - Атрибуты содержимого - 2021
HTML элемент input атрибут type - Соображения доступности - 2021
HTML элемент input атрибут type - Соображения доступности - 2021

В нашей задаче нас будет интересовать type с состоянием File Upload - состояние Загрузки Файла.

Давайте создадим такой элемент:

<input type="file"></input>

Мы положили этот input внутрь элемента body в простом документе с HTML-разметкой.

Стандартное отображение элемента input с type file
Стандартное отображение элемента input с type file

Теперь на странице документа есть кликабельная кнопка, которая вызовет окно обозревателя (проводника) для выбора директории и файла на ПК.

Нажали на элемент input и открылось окно выбора файла на ПК
Нажали на элемент input и открылось окно выбора файла на ПК

В стандартном поведении выбора файла есть один минус. По умолчанию он позволяет выбирать только один файл из директории. Но нам нужно иметь возможность выбирать несколько разных файлов из директории. Как это исправить?

За "мультифайловость" отвечает атрибут multiple, который может быть установлен у элемента input. Давайте его добавим.

<input type="file" multiple></input>
Выделены 2 файла из input
Выделены 2 файла из input

Теперь можем открыть эти 2 файла.

Открыли 2 файла через input
Открыли 2 файла через input

Как мы видим, надпись "Файл не выбран" сменилась на "Число файлов: 2". И на этом всё. Больше никаких визуальных изменений не произошло.

Шаг второй - JavaScript объект элемента input и его свойство files

Теперь мы можем взаимодействовать с элементом input при помощи языка JavaScript и объектной модели документа - DOM.

Из объекта документа (document) мы можем получить объект нашего элемента input.

document.querySelector("body > input[type=file]")

или

document.getElementsByTagName('input')[0]

На странице он у нас всего один, поэтому мы его легко можем обнаружить.

Получили объект элемента input из документа
Получили объект элемента input из документа

Объект элемента input обладает очень большим количеством свойств. Я насчитал 253 свойства в 2021 году. Но нас интересует только одно свойство, которое называется files.

Свойство files объекта input
Свойство files объекта input

Свойство files хранит в себе объект, прототипом которого является класс FileList

По сути это массив, который состоит из объектов File, где свойствами перечислены основные значения любого файла:

  • lastModified
  • lastModifiedDate
  • name
  • size
  • type
  • webkitRelativePath

Из всех этих вложенных свойств нас будет интересовать только свойство с ключом name. Именно в значении хранится нужное нам имя файла.

Объекты File из FileList и их свойства name
Объекты File из FileList и их свойства name

Для получения FIleList

document.querySelector("body > input[type=file]").files

 

Шаг третий - Вывод имён на текущую страницу в элемент body

Теперь можно вывести нужные нам имена файлов прямо под элементом input. Для этого конвертируем объект FIleList в массив.

[...document.querySelector("body > input[type=file]").files]

и проходим по каждому файлу. Методом map() возвращаем только значения свойств name

[...document.querySelector("body > input[type=file]").files].map(i=>i.name)

Получили массив из имён файлов
Получили массив из имён файлов

Теперь мы можем пройти по каждому имени из массива и превратить их в абзацы.

[...document.querySelector("body > input[type=file]").files].map(i=>i.name)
 .map(x=>{
   let newp = document.createElement('p');
   newp.innerText = x;
   document.body.append(newp)
 })

И после этого мы получаем

Вывели имена файлов на текущую страницу - JavaScript
Вывели имена файлов на текущую страницу - JavaScript

 

Шаг четвёртый - Автоматизация вывода имён файлов при загрузке новых файлов

Все предыдущие манипуляции мы делали вручную пошагово, когда состояние объекта input менялось от пустого (безфайлового) до полного (с какими-то загруженными файлами из папки). То есть мы сами точно знали, что состояние изменилось и только тогда выводили имена. Как это автоматизировать?

Для этого нам понадобится слушатель события. Этот слушатель мы повесим на элемент input и когда его состояние будет меняться, мы будем выводить имена файлов на страницу. Как это сделать?

На этот раз нам нужно добавить в наш файл элемент скрипта. Внутри мы будем расписывать логику обработки желаемого поведения.

Для начала в переменной inputfiles мы будем хранить наш элемент ввода - input.

let inputfiles = document.querySelector("body > input[type=file]")

Теперь повесим на него слушатель событий методом addEventListener(type, callback, options)

inputfiles.addEventListener('change', event => {})

В качестве события мы будем использовать событие изменения элемента - 'change'. Когда мы будем выбирать файлы на ПК, тогда состояние нашего элемента ввода будет меняться. Мы будем перехватывать это изменение и выполнять нужные нам действия.

Полная версия документа:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<input type="file" multiple></input>

<script>
let inputfiles = document.querySelector("body > input[type=file]")
inputfiles.addEventListener('change', event => {
  // Очищаем body от возможных старых имён файлов
  [...document.body.children].slice(1).map(i=>i.remove());
  // Добавляем новые имена файлов
  [...event.target.files].map(i=>{
    let newp = document.createElement('p');
    newp.innerText = i.name;
    document.body.append(newp);
  })
})
</script>

</body>
</html>

Выражение event.target будет возвращать нам элемент input, тот единственный, состояние которого может меняться.

 

Информационные ссылки

Стандарт HTML - Элемент input - https://html.spec.whatwg.org/multipage/input.html#the-input-element

Стандарт HTML - Элемент input - https://html.spec.whatwg.org/multipage/input.html#common-input-element-apis

Стандарт HTML - События элемента input - https://html.spec.whatwg.org/multipage/input.html#concept-input-apply

Стандарт DOM - Добавление слушателя события - Метод addEventListener(type, callback, options) - https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener

Поделись записью