Статьи

Играя с API файловой системы HTML5

HTML5 предоставляет нам целый ряд новых возможностей, таких как рисование на холсте , реализация мультимедиа с помощью API аудио и видео и так далее. Одним из этих инструментов, который все еще является относительно новым, является API файловой системы . Это дает нам доступ к изолированному разделу локальной файловой системы пользователя, тем самым еще больше заполняя разрыв между настольными и веб-приложениями! В сегодняшнем уроке мы рассмотрим основы этого нового и интересного API, исследуя наиболее распространенные задачи файловой системы. Давайте начнем!


Нам больше не нужно загружать и устанавливать определенное программное обеспечение, чтобы использовать его. Просто веб-браузер и подключение к Интернету дают нам возможность использовать любое веб-приложение в любое время, в любом месте и на любой платформе.

Короче говоря, веб-приложения это круто; но по сравнению с настольными приложениями у них все еще есть один существенный недостаток: у них нет способа взаимодействовать и организовывать данные в структурированную иерархию папок — настоящую файловую систему. К счастью, с помощью нового API файловой системы это можно изменить. Этот API предоставляет веб-приложениям контролируемый доступ к частной локальной файловой системе «песочницы», в которой они могут записывать и читать файлы, создавать и перечислять каталоги и т. Д. Хотя на момент написания этой статьи только браузер Google Chrome поддерживал «полную» реализацию API файловой системы, он все еще заслуживает изучения как мощная и удобная форма локального хранилища.

Могу ли я использовать поддержку

Файловая система API поставляется в двух разных версиях. Асинхронный API, который полезен для обычных приложений, и синхронный API, зарезервированный для использования с веб-работниками. В целях данного руководства мы будем изучать только асинхронную версию API.


Ваш первый шаг — получить доступ к файловой системе HTML5, запросив системный объект window.requestFileSystem() глобального метода window.requestFileSystem() :

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

В качестве первых двух параметров вы указываете время жизни и размер желаемой файловой системы. PERSISTENT файловая система подходит для веб-приложений, которые хотят постоянно хранить пользовательские данные. Браузер не удалит его, кроме как по явному запросу пользователя. ВРЕМЕННАЯ файловая система подходит для веб-приложений, которые хотят кэшировать данные, но все еще могут работать, если веб-браузер удаляет файловую систему. Размер файловой системы указывается в байтах и ​​должен быть разумным верхним пределом объема данных, которые необходимо хранить.

Третий параметр — это функция обратного вызова, которая запускается, когда пользовательский агент успешно предоставляет файловую систему. Его аргумент является объектом FileSystem . И, наконец, мы можем добавить дополнительную функцию обратного вызова, которая вызывается при возникновении ошибки или при отклонении запроса на файловую систему. Его аргумент является объектом FileError . Хотя этот параметр является необязательным, всегда полезно отлавливать ошибки для пользователей, поскольку существует ряд мест, где что-то может пойти не так.

Файловая система, полученная с помощью этих функций, зависит от происхождения содержащего документа. Все документы или веб-приложения из одного источника (хост, порт и протокол) совместно используют файловую систему. Два документа или приложения из разных источников имеют совершенно разные и непересекающиеся файловые системы. Файловая система ограничена одним приложением и не может получить доступ к данным другого приложения. Он также изолирован от остальных файлов на жестком диске пользователя, и это хорошо: веб-приложение не может «вырваться» за пределы локального корневого каталога или иным образом получить доступ к произвольным файлам.

Давайте рассмотрим пример:

Это создает временную файловую систему с 5 МБ памяти. Затем он предоставляет функцию обратного вызова, которую мы будем использовать для работы нашей файловой системы. И, конечно же, добавлен обработчик ошибок — на случай, если что-то пойдет не так. Здесь errorHandler() является слишком общей. Поэтому, если вы хотите, вы можете создать слегка оптимизированную версию, которая дает читателю более понятное сообщение об ошибке:

Получаемый вами объект файловой системы имеет name (уникальное имя для файловой системы, назначаемое браузером) и root свойство, которое относится к корневому каталогу файловой системы. Это объект DirectoryEntry , и он может иметь вложенные каталоги, которые сами представлены объектами DirectoryEntry . Каждый каталог в файловой системе может содержать файлы, представленные объектами FileEntry . Объект DirectoryEntry определяет методы для получения объектов DirectoryEntry и FileEntry по пути (они могут создавать новые каталоги или файлы, если вы укажете несуществующее имя). DirectoryEntry также определяет фабричный метод createReader() который возвращает объект DirectoryReader для перечисления содержимого каталога. Класс FileEntry определяет метод для получения объекта File (Blob), который представляет содержимое файла. Затем вы можете использовать объект FileReader для чтения файла. FileEntry определяет другой метод для возврата объекта FileWriter , который можно использовать для записи содержимого в файл.

Фуф … звучит сложно? Не беспокойся Все станет яснее по мере продвижения по примерам ниже.


Очевидно, что первое, что вам нужно создать в файловой системе, это несколько блоков или каталогов. Хотя корневой каталог уже существует, вы не хотите помещать туда все свои файлы. Каталоги создаются объектом DirectoryEntry . В следующем примере мы создаем каталог с именем Documents в корневом каталоге:

Метод getDirectory() используется как для чтения, так и для создания каталогов. В качестве первого параметра вы можете указать имя или путь в качестве каталога для поиска или создания. Мы устанавливаем для второго аргумента значение true , потому что мы пытаемся создать каталог, а не читать существующий. И в конце добавляем сообщение об ошибке.

Все идет нормально. У нас есть каталог; давайте теперь добавим подкаталог. Функция точно такая же с одним отличием: мы меняем первый аргумент с «Документы» на «Документы / Музыка». Достаточно просто; но что, если вы хотите создать подпапку Sky с двумя родительскими папками Images и Nature внутри папки Documents ? Если вы введете « Documents/Images/Nature/Sky » в качестве аргумента пути, вы получите сообщение об ошибке, поскольку вы не можете создать каталог, если его непосредственный родитель не существует. Решением для этого является создание каждой папки одна за другой: Images внутри Documents , Nature внутри Images , а затем Sky внутри Nature . Но это очень медленный и неудобный процесс. Есть лучшее решение: создать функцию, которая будет автоматически создавать все необходимые папки.

С помощью этой маленькой хитрости все, что нам нужно сделать, это предоставить полный путь, представляющий папки, которые мы хотим создать. Теперь каталог Sky успешно создан, и вы можете создавать в нем другие файлы или каталоги.

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

В приведенном выше коде свойства isDirectory и isFile используются для получения различного вывода для каталогов и файлов соответственно. Кроме того, мы используем свойство fullPath , чтобы получить полный путь к записи, а не только ее имя.

Есть два способа удалить DirectoryEntry из файловой системы: remove() и removeRecursively() . Первый удаляет данный каталог, только если он пуст. В противном случае вы получите ошибку.

Если в папке « Music » есть файлы, вам нужно использовать второй метод, который рекурсивно удаляет каталог и все его содержимое.


Теперь, когда мы знаем, как создавать каталоги, пришло время заполнить их файлами!

В следующем примере создается пустой test.txt в корневом каталоге:

Первый аргумент getFile() может быть абсолютным или относительным путем, но он должен быть действительным. Например, ошибочно пытаться создать файл, когда его непосредственный родитель не существует. Второй аргумент — это литерал объекта, описывающий поведение функции, если файл не существует. В этом примере create: true создает файл, если он не существует, и выдает ошибку, если он существует ( exclusive: true ). В противном случае, если create: false , файл просто выбирается и возвращается.

Наличие пустого файла не очень полезно; так что давайте добавим контент внутри. Мы можем использовать объект FileWriter для этого.

Выше мы извлекаем файл test.txt и создаем для него объект FileWriter . Затем мы добавляем к нему содержимое, создавая новый объект BlobBuilder и используя метод write() FileWriter .

Вызов getFile() возвращает только FileEntry . Он не возвращает содержимое файла. Итак, если мы хотим прочитать содержимое файла, нам нужно использовать объект File объект FileReader .

Мы записали некоторый контент в наш файл, но что если вы захотите добавить больше на более поздний срок? Чтобы добавить данные в существующий файл, FileWriter используется еще раз. Мы можем переместить писателя в конец файла, используя метод seek() . seek принимает смещение байта в качестве аргумента и устанавливает позицию записывающего файла в это смещение.

Чтобы удалить файл из файловой системы, просто вызовите entry.remove() . Первым аргументом этого метода является функция обратного вызова с нулевым параметром, которая вызывается при успешном удалении файла. Вторым является необязательный обратный вызов ошибок, если возникают какие-либо ошибки.


FileEntry и DirectoryEntry одни и те же методы API для копирования, перемещения и переименования записей. Для этих операций вы можете использовать два метода: copyTo() и moveTo() . Они оба принимают одинаковые параметры:

Первый параметр — это родительская папка, в которую нужно переместить / скопировать запись. Второе — необязательное новое имя, чтобы дать перемещенную / скопированную запись, которая фактически требуется, когда вы копируете запись в той же папке; в противном случае вы получите ошибку. Третий и четвертый параметры были объяснены ранее.

Давайте рассмотрим несколько простых примеров. В следующем test.txt мы копируем файл test.txt из root каталога в каталог Documents .

Следующий пример перемещает test.txt в Documents вместо его копирования:

Следующий пример переименовывает test.txt в text.txt :


В этом вводном уроке мы только коснулись поверхности различных интерфейсов файловой системы. Если вы хотите узнать больше и углубиться в API файловой системы, вам следует обратиться к спецификациям спецификаций W3C:

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


Файловая система API — это мощная и простая в использовании технология, которая предоставляет веб-разработчикам целый ряд новых возможностей при создании веб-приложений. По общему признанию, это все еще довольно ново и не широко поддержано всеми основными браузерами, но это конечно изменится в будущем. Вы могли бы также получить преимущество!