30 січня 2022 р.

File та FileReader

Об’єкт File наслідується від Blob та надає додаткові можливості для роботи з файловою системою.

Є два способи створити екземпляр File.

По-перше, можна скористатися конструктором схожим на Blob:

new File(fileParts, fileName, [options])
  • fileParts – масив значень, що можуть мати тип Blob/BufferSource/String.
  • fileName – рядок з іменем файлу.
  • options – необов’язковий об’єкт з властивостями:
    • lastModified – мітка часу (ціле число) останньої зміни.

По-друге, частіше ми отримуємо файл із <input type="file">, перетягуванням чи іншим способом. У такому випадку інформацію про файл заповнює ОС.

Оскільки клас File наслідує Blob, екземпляри File мають такі самі властивості і ще додаткові:

  • name – ім’я файлу,
  • lastModified – мітка часу останньої зміни.

Щоб отримати об’єкт File з <input type="file"> потрібно:

<input type="file" onchange="showFile(this)">

<script>
function showFile(input) {
  let file = input.files[0];

  alert(`Ім’я файлу: ${file.name}`); // наприклад my.png
  alert(`Дата останньої зміни: ${file.lastModified}`); // наприклад 1552830408824
}
</script>
Будь ласка, зверніть увагу:

Компонент введення (input) дозволяє обрати декілька файлів разом, які будуть доступні в об’єкті input.files. Оскільки тут ми завантажуємо один файл, то можемо скористатися input.files[0].

FileReader

FileReader – об’єкт для зчитування даних з Blob, а отже і з File також.

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

Конструктор:

let reader = new FileReader(); // без аргументів

Основні методи:

  • readAsArrayBuffer(blob) – прочитати дані в бінарному форматі і зберегти в ArrayBuffer.
  • readAsText(blob, [encoding]) – прочитати дані як текст із заданим кодуванням (типово utf-8).
  • readAsDataURL(blob) – прочитати бінарні дані та закодувати у форматі base64 data url.
  • abort() – відмінити операцію.

Вибір read* методу залежить від формату даних з яким ми хочемо працювати.

  • readAsArrayBuffer – використовується для низькорівневих операцій з бінарними даними. Для високорівневих операцій, як отримання зрізів, об’єкт File успадковується від Blob, тому його можна використовувати безпосередньо без читання файлу.
  • readAsText – використовується для текстових файлів, вміст буде записано в рядок.
  • readAsDataURL – використовується, якщо ми хочемо використати дані як вміст src тегу img або інших. Можна скористатися іншим способом для цього, що описано в розділі Blob: URL.createObjectURL(file).

Протягом зчитування файлу можуть виникнути події:

  • loadstart – зчитування файлу почалось.
  • progress – періодично виникає протягом зчитування.
  • load – зчитування завершилось без помилок.
  • abort – викликано метод abort().
  • error – протягом зчитування виникла помилка.
  • loadend – зчитування закінчилось успішно чи з помилкою.

Після закінчення зчитування файлу результат можна отримати за допомогою:

  • reader.result якщо зчитування закінчилося успішно, без помилки
  • reader.error якщо протягом зчитування виникла помилка.

Найпотрібніші події при зчитуванні файлу: load та error.

Приклад зчитування файлу:

<input type="file" onchange="readFile(this)">

<script>
function readFile(input) {
  let file = input.files[0];

  let reader = new FileReader();

  reader.readAsText(file);

  reader.onload = function() {
    console.log(reader.result);
  };

  reader.onerror = function() {
    console.log(reader.error);
  };

}
</script>
FileReader для Blob

Як описано в розділі Blob, FileReader може зчитати вміст будь-яких бінарних об’єктів, а не тільки файлів.

Це можна використати для перетворення бінарних Blob об’єктів у інші формати:

  • readAsArrayBuffer(blob) – в ArrayBuffer,
  • readAsText(blob, [encoding]) – в рядок (альтернативний спосіб до TextDecoder),
  • readAsDataURL(blob) – в формат base64-кодованого url.
FileReaderSync доступний всередині Web Workers

Для Web Workers існує FileReaderSync – синхронний варіант FileReader.

Його метод read* не створює подій, а просто повертає результат, як звичайна функція.

Синхронний метод бажано використовувати тільки всередині Web Worker, бо затримки під час синхронного виклику, що ймовірні при синхронному читанні з файлів, в Web Worker є менш важливими. Вони не впливають на сторінку.

Підсумки

File успадковується від Blob.

На додачу до методів та властивостей, що доступні в Blob, об’єкт File має властивості name, lastModified та ще можливість читати файли з файлової системи. Переважно об’єкт File отримується з користувацького вводу, як <input> чи Drag’n’Drop подіями (ondragend).

FileReader об’єкт може прочитати з файлу чи blob в одному з трьох форматів:

  • Рядок (readAsText).
  • ArrayBuffer (readAsArrayBuffer).
  • URL в форматі base-64 (readAsDataURL).

У багатьох випадках нам не потрібно читати увесь вміст файлу. Так же як і з blob, ми можемо створити коротке посилання за допомогою URL.createObjectURL(file) та присвоїти його тегу <a> чи <img>. Таким чином файл можна завантажити чи показати як зображення, як частину вмісту canvas тощо.

Також легко відправити File мережею, бо мережеве API XMLHttpRequest чи fetch можуть безпосередньо працювати з об’єктами File.

Навчальна карта