Файловое поле

Файловое поле изначально было предназначено для закачивания файлов с компьютера через форму. В современных браузерах они также позволяют читать файлы из JavaScript. Поле работает как охранник для файлов. Скрипт не может просто взять и открыть файл с компьютера пользователя, но если тот выбрал файл в этом поле, браузер разрешает скрипту начать чтение файла.

Файловое поле обычно выглядит как кнопка с надписью вроде «Выберите файл», с информацией про выбранный файл рядом с ней.

<input type="file">

<script>

  var input = document.querySelector("input");

  input.addEventListener("change", function() {

    if (input.files.length > 0) {

      var file = input.files[0];

      console.log("You chose", file.name);

      if (file.type)

        console.log("It has type", file.type);

    }

  });

</script>

Свойство files элемента – массивоподобный объект (не настоящий массив), содержащий список выбранных файлов. Изначально он пуст. У элемента нет простого свойства file, потому что пользователь может выбрать несколько файлов за раз при включённом атрибуте multiple.

У объектов в свойстве files есть свойства имя (имя файла), размер (размер файла в байтах), и тип (тип файла в смысле media type — text/plain или image/jpeg).

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

<input type="file" multiple>

<script>

  var input = document.querySelector("input");

  input.addEventListener("change", function() {

    Array.prototype.forEach.call(input.files, function(file) {

      var reader = new FileReader();

      reader.addEventListener("load", function() {

        console.log("File", file.name, "starts with",

                    reader.result.slice(0, 20));

      });

      reader.readAsText(file);

    });

  });

</script>

Чтение файла происходит при помощи создания объекта FileReader, регистрации события “load” для него, и вызова его метода readAsText с передачей тому файла. По окончанию загрузки в свойстве result сохраняется содержимое файла.

Пример использует Array.prototype.forEach для прохода по массиву, так как в обычном цикле было бы неудобно получать нужные объекты file и reader от обработчика событий. Переменные были бы общими для всех итераций цикла.

У FileReaders также есть событие “error”, когда чтение файла не получается. Объект error будет сохранён в свойстве error. Если вы не хотите забивать голову ещё одной неудобной асинхронной схемой, вы можете обернуть её в обещание (см. главу 17):

function readFile(file) {

  return new Promise(function(succeed, fail) {

    var reader = new FileReader();

    reader.addEventListener("load", function() {

      succeed(reader.result);

    });

    reader.addEventListener("error", function() {

      fail(reader.error);

    });

    reader.readAsText(file);

  });

}

Возможно читать только часть файла, вызывая slice и передавая результат (т. н. объект blob) объекту reader.

Более 800 000 книг и аудиокниг! 📚

Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением

ПОЛУЧИТЬ ПОДАРОК