<input type="file">
Елементи <input>
з атрибутом type="file"
дають користувачеві змогу обрати один чи більше файлів з його пристрою. Бувши обраними, файли можуть бути завантажені на сервер за допомогою подання форми, або ж використані за допомогою коду на JavaScript та файлового API.
Спробуйте його в дії
Значення
Атрибут файлового поля value
містить рядок, що представляє шлях до обраного файлу (або файлів). Поки жоден файл не обраний, значенням є порожній рядок (""
). Коли користувач обирає декілька файлів, то value
представляє перший файл з обраних. Решта файлів можуть бути встановлені за допомогою властивості поля HTMLInputElement.files
.
[!NOTE] Значенням завжди є ім'я файлу, перед котрим додано
C:\fakepath\
(англ.), що не є справжнім шляхом до файлу. Так зроблено, щоб не дати зловмисним програмам дізнатися про файлову структуру пристрою користувача.
Додаткові атрибути
На додачу до загальних атрибутів, що їх поділяють усі елементи <input>
, поля типу file
також підтримують наступні:
accept
Значення атрибута accept
– рядок, що визначає типи файлів, котрі повинно приймати файлове поле. Цей рядок – розділений комами список унікальних вказівок типу файлу. Оскільки певний тип файлу може бути ідентифікований більш ніж одним способом, слушно надавати повний набір вказівок типу, коли необхідні файли конкретного формату.
Наприклад, є низка способів ідентифікувати файли Microsoft Word, тому сайт, що приймає файли Word, може використовувати <input>
такого виду:
<input
type="file"
id="docpicker"
accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
capture
Значення атрибута capture
– рядок, що вказує яку камеру слід використовувати для захоплення фото чи відео, якщо атрибут accept
вказує, що введені дані повинні бути фото чи відео. Значення user
("користувач") вказує, що повинні використовуватися фронтальні камера чи мікрофон. Значення environment
("середовище") вказує, що повинні використовуватися камера чи мікрофон, спрямовані назовні. Якщо такого атрибута немає, то користувацький агент вільний сам вирішувати, що робити. Якщо вказаний фронтальний режим, але він недоступний, то користувацький агент може відступити до свого усталеного режиму.
[!NOTE] Атрибут
capture
раніше був булевим і призводив до запиту на використання захоплення медіа, камери чи мікрофона, а не введення файлу.
multiple
Коли вказаний булів атрибут multiple
, то файлове поле дозволяє користувачеві вибрати більш ніж один файл.
Нестандартні атрибути
На додачу до вище перелічених атрибутів, у деяких браузерах доступні наступні нестандартні атрибути. Слід уникати їх використання, коли це можливо, адже воно обмежує змогу вашого коду діяти в браузерах, що не мають їх реалізації.
webkitdirectory
Булів атрибут webkitdirectory
, коли присутній, вказує, що для вибору користувачем в інтерфейсі вибору файлу повинні бути доступні лише директорії. Дивіться HTMLInputElement.webkitdirectory
для отримання подробиць та прикладів.
Бувши спершу реалізованим лише в браузерах на основі WebKit, webkitdirectory
також працює в Microsoft Edge, а також Firefox 50 і новішим. Втім, навіть попри його відносно широку підтримку, він все ж є нестандартним і не повинен використовуватись, окрім випадків, коли немає інших варіантів.
Унікальні вказівки типу файлу
Унікальна вказівка типу – рядок, що описує тип файлу, котрий може бути обраний користувачем в елементі <input>
типу file
. Кожна унікальна вказівка типу файлу може приймати одну з наступних форм:
- Дійсне байдуже до регістру розширення імені файлу, що починається з символу крапки ("."). Наприклад:
.jpg
,.pdf
,.doc
. - Чинний рядок типу MIME, без розширень.
- Рядок
audio/*
, що означає "будь-який файл аудіо". - Рядок
video/*
, що означає "будь-який файл відео". - Рядок
image/*
, що означає "будь-який файл зображення".
Атрибут accept
приймає за значення рядок, що містить одну чи більше таких унікальних вказівок типу файлу, розділених комами. Наприклад, вибір файлу, що потребує вмісту, котрий може бути представлений як зображення, включно зі стандартними форматами зображень і файлами PDF, може мати такий вигляд:
<input type="file" accept="image/*,.pdf" />
Використання файлових полів
Найпростіший приклад
<form method="post" enctype="multipart/form-data">
<div>
<label for="file">Оберіть файл для завантаження</label>
<input type="file" id="file" name="file" multiple />
</div>
<div>
<button>Надіслати</button>
</div>
</form>
This produces the following output:
[!NOTE] Також цей приклад можна знайти на GitHub, дивіться вихідний код, а також погляньте на нього в дії.
Незалежно від пристрою чи операційної системи користувача, файлове поле надає кнопку, що відкриває діалог вибору файлу, котрий дає користувачеві змогу вибрати файл.
Включення атрибута multiple
, як показано вище, вказує, що водночас можуть бути обрані декілька файлів. Користувач може обрати декілька файлів у будь-який спосіб, котрий пропонує його платформа (наприклад, утримуючи натисненою клавішу Shift або Control, а потім клацаючи). Якщо необхідно, щоб користувач міг обрати лише один файл в одному <input>
, слід упустити атрибут multiple
.
Отримання інформації про вибрані файли
Вибрані файли повертає властивість елемента HTMLInputElement.files
, причому повертає у вигляді об'єкта FileList
, що зберігає список об'єктів File
objects. FileList
поводиться подібно до масиву, тож для отримання числа вибраних файлів можна перевірити властивість length
.
Кожний об'єкт File
містить наступну інформацію:
name
(ім'я)Ім'я файлу.
lastModified
(востаннє змінений)Число, що вказує дату й час, коли файл востаннє був змінений, у вигляді мілісекунд, що минули від початку епохи UNIX (опівночі 1 січня 1970 року).
lastModifiedDate
(дата останніх змін)Об'єкт
Date
, що представляє дату й час, коли файл востаннє був змінений. Ця властивість є нерекомендованою. Замість неї слід використовуватиlastModified
.size
(розмір)Розмір файлу в байтах.
type
(тип)MIME-тип файлу.
webkitRelativePath
(відносний шлях WebKit)Рядок, що представляє шлях до файлу відносно базової директорії, обраної при виборі директорії (тобто в інтерфейсі вибору
file
, що має атрибутwebkitdirectory
. Ця властивість є нестандартною, її слід використовувати з обережністю.
[!NOTE] У всіх сучасних браузерах значення
HTMLInputElement.files
можна як отримати, так і встановити; останнім з браузерів цю функціональність додав Firefox у версії 57 (дивіться ваду Firefox 1384030).
Обмеження прийнятних типів файлу
Часто не хочеться давати користувачеві змогу обрати файл будь-якого довільного типу; натомість часто хочеться дозволити йому обирати файли певного типу чи типів. Наприклад, якщо файлове поле дає користувачам змогу завантажити зображення профілю, то, ймовірно, ви хочете дозволити вибрати сумісні з вебом формами зображень, наприклад, JPEG чи PNG.
Прийнятні типи файлу можна задати за допомогою атрибута accept
, котрий приймає список дозволених розширень файлу чи MIME-типів, розділених комами. Трохи прикладів:
accept="image/png"
чиaccept=".png"
— приймає файли PNG.accept="image/png, image/jpeg"
чиaccept=".png, .jpg, .jpeg"
— Приймає файли PNG чи JPEG.accept="image/*"
— Приймає будь-який файл з MIME-типомimage/*
. (Чимало мобільних пристроїв також дозволять користувачеві зробити фото за допомогою камери, коли таке застосовується.)accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
— приймає що завгодно, від чого віє документом MS Word.
Погляньмо на повніший приклад:
<form method="post" enctype="multipart/form-data">
<div>
<label for="profile_pic">Оберіть файл для завантаження</label>
<input
type="file"
id="profile_pic"
name="profile_pic"
accept=".jpg, .jpeg, .png" />
</div>
<div>
<button>Надіслати</button>
</div>
</form>
Це породжує вивід, подібний до того, що був у попередньому прикладі:
[!NOTE] Цей приклад також можна знайти на GitHub, – дивіться вихідний код, а також той самий приклад у дії.
Це може здаватися схожим, але якщо спробувати вибрати файл із таким полем, то стане помітно, що інтерфейс вибору файлу дозволяє вибрати файли лише тих типів, що вказані у значенні accept
(конкретний інтерфейс відрізняється в різних браузерах та операційних системах).
Атрибут accept
не перевіряє типи вибраних файлів; цей атрибут підказує браузерам, як підвести користувачів до вибору відповідних типів файлів. Усе ж можливо (в більшості випадків) вимкнути при виборі файлу це обмеження і вибрати будь-який бажаний файл, із некоректним типом.
У зв'язку з цим слід пересвідчитися, що атрибут accept
доповнений відповідною валідацією на боці сервера.
Відстеження скасувань
Подія cancel
спрацьовує тоді, коли користувач не змінює свого вибору, повторно вибираючи раніше вибрані файли. Також вона спрацьовує, коли діалог вибору файлу закривається чи скасовується за допомогою кнопки "скасувати" або клавіші escape.
Наприклад, наступний код виведе повідомлення в консоль, якщо користувач закриє спливне вікно, не вибравши файл:
const elem = document.createElement("input");
elem.type = "file";
elem.addEventListener("cancel", () => {
console.log("Скасовано.");
});
elem.addEventListener("change", () => {
if (elem.files.length == 1) {
console.log("Вибрано файл: ", elem.files[0]);
}
});
elem.click();
Примітки
-
Не можна встановити значення файлового поля зі сценарію, – код типу того, що нижче, не подіє:
const input = document.querySelector("input[type=file]"); input.value = "foo";
-
Коли за допомогою
<input type="file">
обирається файл, реальний шлях до такого файлу з очевидних міркувань безпеки не показується в атрибутіvalue
. Натомість його ім'я показується ізC:\fakepath\
на початку. Цей виверт має певні історичні підстави, але він підтримується у всіх сучасних браузерах і фактично є визначеним специфікацією (англ.).
Приклади
У цьому прикладі представлений дещо ускладнений вибір файлу, що користується інформацією про файл, доступною у властивості HTMLInputElement.files
, а також демонструє кілька кмітливих фокусів.
[!NOTE] Повний вихідний код цього прикладу доступний на GitHub: file-example.html (дивіться також у дії). Пояснювати CSS не будемо, JavaScript є головною темою.
Перш за все, погляньмо на HTML:
<form method="post" enctype="multipart/form-data">
<div>
<label for="image_uploads"
>Оберіть зображення для завантаження (PNG, JPG)</label
>
<input
type="file"
id="image_uploads"
name="image_uploads"
accept=".jpg, .jpeg, .png"
multiple />
</div>
<div class="preview">
<p>Наразі жодні файли не вибрані для завантаження</p>
</div>
<div>
<button>Надіслати</button>
</div>
</form>
Це подібно до того, що ми вже бачили вище, – нічого додати.
Далі перегляньмо JavaScript.
У перших рядках сценарію отримуються посилання на саме поле форми, а також елемент <div>
із класом .preview
. Далі – приховується елемент <input>
: це необхідно, тому що файлові поля мають тенденцію до потворності, складності в оформленні та неодноманітності в дизайні між різними браузерами. Елемент input
можна активувати, клацнувши його <label>
, тож краще візуально приховати input
і оформити label
як кнопку, щоб користувач знав, що для завантаження файлів взаємодіяти треба із label
.
const input = document.querySelector("input");
const preview = document.querySelector(".preview");
input.style.opacity = 0;
[!NOTE] Для приховування файлового поля використовується
opacity
, а неvisibility: hidden
чиdisplay: none
, тому що допоміжні технології інтерпретують два останні стилі так, ніби файлове поле не є інтерактивним.
Далі – до поля додається слухач подій, щоб відстежувати зміни його значення (у цьому випадку це відповідає вибору файлів). Слухач подій викликає самописну функцію updateImageDisplay()
.
input.addEventListener("change", updateImageDisplay);
Кожного виклику функції updateImageDisplay()
:
-
Для очищення попереднього вмісту
<div>
із попереднім виглядом використовується циклwhile
. -
Витягується об'єкт
FileList
, що містить інформацію про всі вибрані файли, та зберігається у змінній, названійcurFiles
. -
За допомогою порівняння
curFiles.length
із 0 виконується перевірка, чи не було вибрано 0 (нуль) файлів. Якщо є рівність, то в<div>
попереднього вигляду виводиться повідомлення про те, що жодні файли не були вибрані. -
Якщо файли були вибрані, то відбувається обхід кожного з них, – із виводом інформації про них у
<div>
попереднього вигляду. Слід зауважити, що: -
Для перевірки, чи належить файл до коректного типу (наприклад, типів зображень, зазначених в атрибуті
accept
), використовується самописна функціяvalidFileType()
. -
Якщо він справді належить до коректного типу, то:
- Його ім'я та розмір (отримані з
file.name
іfile.size
) виводяться в елемент списку всередині попереднього<div>
. Самописна функціяreturnFileSize()
повертає приємно відформатовану версію розміру, в байтах, кілобайтах, мегабайтах (усталено браузер звітує про розмір в абсолютних байтах). - Шляхом виклику
URL.createObjectURL(file)
генерується ескіз зображення. Потім – за допомогою створення нового<img>
і присвоєння його атрибутовіsrc
ескізу – зображення вставляється в елемент списку.
- Його ім'я та розмір (отримані з
-
Якщо тип файлу є недійсним, то всередині елемента списку виводиться повідомлення, що сповіщає користувача про необхідність вибрати файл іншого типу.
function updateImageDisplay() {
while (preview.firstChild) {
preview.removeChild(preview.firstChild);
}
const curFiles = input.files;
if (curFiles.length === 0) {
const para = document.createElement("p");
para.textContent = "Наразі жодні файли не вибрані для завантаження";
preview.appendChild(para);
} else {
const list = document.createElement("ol");
preview.appendChild(list);
for (const file of curFiles) {
const listItem = document.createElement("li");
const para = document.createElement("p");
if (validFileType(file)) {
para.textContent = `Ім'я файлу – ${
file.name
}, розмір файлу – ${returnFileSize(file.size)}.`;
const image = document.createElement("img");
image.src = URL.createObjectURL(file);
image.alt = image.title = file.name;
listItem.appendChild(image);
listItem.appendChild(para);
} else {
para.textContent = `Ім'я файлу – ${file.name}: недійсний тип файлу. Оновіть свій вибір.`;
listItem.appendChild(para);
}
list.appendChild(listItem);
}
}
}
Самописна функція validFileType()
приймає як параметр об'єкт File
, а потім використовує Array.prototype.includes()
, щоб перевірити, чи відповідає будь-яке з fileTypes
значення властивості файлу type
. Якщо відповідність знайдена, то функція повертає true
. Якщо не знайдена – false
.
// https://webdoky.org/uk/docs/Web/Media/Formats/Image_types
const fileTypes = [
"image/apng",
"image/bmp",
"image/gif",
"image/jpeg",
"image/pjpeg",
"image/png",
"image/svg+xml",
"image/tiff",
"image/webp",
"image/x-icon",
];
function validFileType(file) {
return fileTypes.includes(file.type);
}
Функція returnFileSize()
приймає число (байтів, отримане з властивості size
відповідного файлу) і перетворює його на приємно відформатований розмір у байтах, кілобайтах, мегабайтах.
function returnFileSize(number) {
if (number < 1e3) {
return `${number} bytes`;
} else if (number >= 1e3 && number < 1e6) {
return `${(number / 1e3).toFixed(1)} кБ`;
} else {
return `${(number / 1e6).toFixed(1)} МБ`;
}
}
[!NOTE] Одиниці вимірювання "кБ" і "МБ" тут використовують прийняті префікси міжнародної системи числення (SI): 1 кБ = 1000 Б, подібно до того, як це працює в macOS. Інші системи представляють розміри файлів інакше: наприклад, Ubuntu користується префіксами Міжнародної електротехнічної комісії (IEC), в яких 1 КіБ = 1024 Б, а специфікації RAM нерідко використовують префікси SI для представлення степенів двійки (1 кБ = 1024 Б). У зв'язку з цим тут використовуються
1e3
(1000
) і1e6
(100000
), а не1024
і1048576
. У власному застосунку вам слід чітко роз'яснити систему одиниць вимірювання користувачам, якщо важливий точний розмір.
Приклад має наступний вигляд; пограйтеся:
Технічний підсумок
Значення | Рядок, що представляє шлях до вибраного файлу. |
Події |
change , input і cancel
|
Підтримувані загальні атрибути | required |
Додаткові атрибути |
accept ,
capture ,
multiple
|
Атрибути IDL | files і value |
Інтерфейс DOM | |
Методи |
select()
|
Неявна роль ARIA | немає відповідної ролі |
Специфікації
Специфікація |
---|
HTML Standard (HTML) # file-upload-state-(type=file) |
Сумісність із браузерами
desktop | mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
type="file"
|
Chrome Full support 1 | Edge Full support 12 | Firefox Full support 1 | Internet Explorer Full support Так | Opera Full support 11 | Safari Full support 1 | WebView Android Full support Так | Chrome Android Full support Так | Firefox for Android Full support 4 | Opera Android Full support 11 | Safari on iOS Full support Так | Samsung Internet Full support Так |
Дивіться також
- Використання файлів у вебзастосунках — містить низку інших корисних прикладів, що стосуються
<input type="file">
і File API. - Сумісність властивостей CSS