Всем привет! Наконец я освободился от всех насущных дел и готов продолжать радовать вас своими статьями по веб программированию.
Тема сегодняшней статьи FileSystem api. Думаю все об этом слышали, но мало кто пробовал работать с данным api из за его слабой поддержки в браузерах. На данный момент FileSystem api поддерживается только в браузере google chrome. Но даже не смотря на это, я все равно расcкажу и покажу как с ним работать, так как это довольно интересный api появившийся вместе со стандартами html5. С данной статьи я начну доносить до вас информацию в новом формате. Надеюсь вы оцените! Поехали!
Для того чтобы начать работать с fileSystem Api проверим его поддержку в браузере! Для этого выполним такой код:
if(window.webkitRequestFileSystem){
console.log("fileSystem api поддерживается!");
}else{
console.log("fileSystem api не поддерживается!");
}
Здесь мы обращаемся к fileSystem api используя специальный префикс webkit, как я уже писал на данный момент поддержка осуществлена только в браузере google chrome.
window.webkitRequestFileSystem
Это главный объект для работы с fileSystem api. Убедившись что все поддерживается переходим к работе.
Нам понадобится сервер, можно использовать локальный. Стоит отметить что файловая система формируется для каждого домена. То есть вы не сможете обмениваться данными из файловых систем с разными доменами. Это те же самые ограничения что для cookie и localStorage.
Обращаемся к файловой системе, получаем все папки и файлы из корневой директории filesystem.
function error(err){
console.log(err);
}
function success(file){
var fileSystem = file.root.createReader();
fileSystem.readEntries (function(results) {
console.log(results);
});
}
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, success, error);
После выполнения данного кода в консоль браузера будет выведен массив со всеми папками и файлами системы. Сейчас пока у нас в файловой системе ничего не записано, поэтому выведется пустой массив. Данная конструкция:
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, success, error);
будет фигурировать во всех операциях. В качестве первого аргумента идет window.TEMPORARY - это ключ (type) доступность хранилища файлов. Здесь также может приниматься значение window.PERSISTENT.
window.TEMPORARY - ключ при котором данные могут удаляться по усмотрению браузера, если к примеру не будет хватать места.
window.PERSISTENT - ключ при котором данные удаляются только с разрешения пользователя ресурса, здесь нужны дополнительные настройки квоты.
Я разберу работу только с ключом window.TEMPORARY! Ключ PERSISTENT оставлю вам в качестве домашнего задания.
Второй аргумент (1024*1024) - это размер необходимой памяти (в байтах) для нашей файловой системы.
Последние два аргумента функции:
success - при успешной отработке
error - функция для вывода ошибок в консоль
Нас интересует функция success. Здесь с помощью данной строчки
var fileSystem = file.root.createReader();
мы в переменную fileSystem получаем корневую директорию файловой системы и затем с помощью метода readEntries считываем файлы.
По итогу нам возвращается массив данных. Отлично, идем дальше!
Рассмотрим создание файлов в filesystem. Для удобства работы, я на каждую операцию буду создавать свою функцию.
function createFile(name, content, type){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(file){
var strblob = new Blob([content], {
type: type
});
file.root.getFile(name, {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.write(strblob);
console.log(fileEntry.toURL());
}, error);
},error);
}, error);
}
createFile("test.html", "<h1>Секретная страница fileSystem api! Тссс...</h1>", "text/html");
В данном примере я создал функцию при вызове которой в файловой системе будут создаваться файл test.html с содержимым "Секретная страница fileSystem api! Тссс..." и в консоль выводится ссылка на файл. Как видите она принимает три аргумента:
- название файла
- содержимое файла
- тип файла
Тип файла нужен для преобразования строки в объект blob, именно в таком формате происходить запись содержимого файла.
Для создания файла используется метод getFile() и в качестве его аргументов идут:
- название файла
- объект с опциями, для создания файла обязательно нужно указывать ключ create со значением true.
- функции обратного вызова, успешное выполнение и ошибка
При успешной отработке будет создан файл и возвращена на него ссылка fileEntry, дальше можно будет делать запись данных.
Делается это при помощи метода createWriter(), мы открываем файл на запись, получаем объект fileWriter и с помощью метода write() записываем данные в формате blob.
Также с помощью метода toURL() можно получить прямую ссылку на файл. В результате должно получится, так:
После выполнения функции createFile() мы создали файл test.html и получили очень странную на первый взгляд ссылку filesystem:http://filesystemapi/temporary/test.html где
http://filesystemapi - мой локальный хост или домен. То есть для того чтобы получить доступ к файлам filesystem api нам необходимо перейти по ссылке такого типа filesystem:{ваш домен}/temporary/{путь к файла}. Обратите внимание что при повторной проверке файловой системы в массиве появится объект нашего файла.
Допустим мы хотим переименовать наш файл test.html в hello.html, для этого создаем функцию:
function rename(path, name){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getFile(path, {}, function(fileEntry) {
fileEntry.moveTo(fs.root, name);
console.log('Файл' + path + ' успешно переименован в ' + name);
}, error);
}, error);
}
rename("test.html", "hello.html");
После выполнения этой функции rename файл test.html будет переименован в hello.html
Первым аргументом функция принимает название файла или путь до него, а вторым новое имя.
Заметьте что и здесь мы используем метод getFile(), только уже без опций. К возвращаемому объекту fileEntry применяется метод moveTo(), который прежде всего предназначается для перемещения файлов и папок. Его работу по предназначению мы еще сегодня рассмотрим.
Переходим к чтению файлов:
function readFile(name){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(file){
file.root.getFile(name, {}, function(fileEntry) {
fileEntry.file(function(read) {
var reader = new FileReader();
reader.onloadend = function(e) {
console.log(this.result);
}
reader.readAsText(read)
}, error);
},error);
}, error);
}
readFile("hello.html");
C помощью данной функции readFile() вы без труда прочитаете текстовый файл. Функция принимает один аргумент - название файла. После получения файла в объект fileEntry для чтения мы используем метод file(). Стоит отметить что информация также возвращается в формате blob, поэтому для ее преобразование в текстовое представление используется fileReader из file api.
В результате в консоли выводится содержимое файла!
Поcмотрим как удаляются файлы:
function removeFile(name){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getFile(name, {create: false}, function(fileEntry) {
fileEntry.remove(function() {
console.log('Файл '+ name+' удален!');
}, error);
}, error);
}, error);
}
removeFile("hello.html");
Для того чтобы удалить файл достаточно к объекту fileEntry применить метод remove(), результат вы увидите сами:
После вызова функции removeFile(), наш файл hello.html был успешно удален из файлового хранилища. Сама функция принимает единственный аргумент - путь к файлу.
Если мы захотим что то записать или дописать в созданный файл, можно воспользоваться моей специально разработанной функцией:
function writeFile(name, content, type, flag=false){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(file){
file.root.getFile(name, {create: false}, function(fileEntry) {
fileEntry.file(function(read) {
var reader = new FileReader();
reader.onloadend = function(e) {
if(!flag){
content = this.result + content;
}else{
removeFile(name);
}
createFile(name, content,type);
}
reader.readAsText(read)
}, error);
},error);
}, error);
}
Функция использует все те функции которые мы описали выше и принимает четыре аргумента:
- путь к файлу
- Записываемые данные
- Формат данных
- Флаг, false(по умолчанию) - данные дописываются в файл, true - данные перезаписывают файл.
Вот пример работы c функцией:
Здесь вначале я создаю новый файл test.txt с записью "hello", затем используя функцию writeFile() записываю новые данные в файл.
Рассмотрим создание и удаление директорий в файловом хранилище.
function createFolder(name){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getDirectory(name, {create: true}, function(dirEntry) {
console.log("Папка "+name+ " Создана!");
}, error);
}, error);
}
createFolder("myFolder");
С помощью функции createFolder() мы создадим папку "myFolder" в нашей файловой системе:
Заметьте что теперь вместо метода getFile() мы используем getDirectory(). Этот метод служит для получения папок файловой системы. Здесь также необходимо передать в опции ключ create со значением true.
Для удаления папки:
function removeFolder(name){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getDirectory(name, {}, function(dirEntry) {
dirEntry.removeRecursively(function() {
console.log('папка '+name+ ' удалена!');
}, error);
}, error);
}, error);
}
removeFolder("myFolder");
После вызова функции removeFolder() указанная папка будет удалена:
Для удаления к объекту папки dirEntry применяется метод removeRecursively(). Это метод служит для рекурсивного удаления, то есть все что будет в папке также удалится.
Последние две операции которые мы рассмотрим будут перемещение и копирование файлов!
Здесь сначала я создаю папку "myFolder". Затем файл test.txt перемещаю в папку "myFolder" с помощью функции moveFile().
function moveFile(path, path2){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getFile(path, {}, function(fileEntry) {
fs.root.getDirectory(path2, {}, function(dirEntry) {
fileEntry.moveTo(dirEntry);
}, error);
}, error);
}, error);
}
Эта функция принимает два аргумента путь до файла который нужно переместить и путь куда переместить. Для объекта файла fileEntry применяется метод moveTo() которому в свою очередь передается объект папки куда будет перемещен файл.
После перемещения я выполняю функцию копирования:
function copyFile(path, path2){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getFile(path, {}, function(fileEntry) {
fs.root.getDirectory(path2, {}, function(dirEntry) {
fileEntry.copyTo(dirEntry);
}, error);
}, error);
}, error);
}
Здесь различия только в методах. Вместо moveTo() используется метод copyTo().
В завершении данной статьи рассмотрим загрузку файлов и в качестве практического примера напишем загрузчик картинок галереи.
Вот общий код:
<input type="file" id="uploadImage"/>
<div class="gallery"></div>
<script>
function error(err){
console.log(err);
}
function success(file){
var fileSystem = file.root.createReader(),span;
fileSystem.readEntries (function(results) {
for(var i = 0; i < results.length; i++){
if(results[i]['name'].search(/\.png$/) !== -1 || results[i]['name'].search(/\.gif$/) !== -1 || results[i]['name'].search(/\.jpg$/) !== -1){
span = document.createElement('span');
span.innerHTML = "<img width='200' src='filesystem:"+document.location.protocol+"//"+document.domain+"/temporary/"+results[i]['name']+"'/>";
span.innerHTML += "<button onclick='deletes_fun(\""+results[i]['name']+"\")'>Удалить</button>";
document.querySelector('.gallery').appendChild(span);
}
}
});
}
function deletes_fun(name){
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getFile(name, {}, function(fileEntry) {
fileEntry.remove(function() {
document.location = document.location.href;
}, error);
}, error);
}, error);
}
document.querySelector("#uploadImage").addEventListener('change', function(e){
var files = this.files;
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024*30, function(fs) {
for (var i = 0, file; file = files[i]; ++i) {
(function(f) {
if(file.name.search(/\.png$/) !== -1 || file.name.search(/\.gif$/) !== -1 || file.name.search(/\.jpg$/) !== -1){
fs.root.getFile(file.name, {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.write(f);
document.location = document.location.href;
}, error);
}, error);
}else{
alert('Разрешена загрузка файлов следующих форматов: png, gif, jpg');
}
})(file);
}
}, error);
});
window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, success, error);
</script>
Здесь мы сделали возможность загрузки изображений в форматах png, jpg и gif прямо в файловое хранилище браузера и теперь картинки будут хранится в нашей файловой системе. Для удаления изображений из хранилища достаточно нажать кнопку удалить.
Вот демонстрация:
Вы можете загружать в файловое хранилище не только картинки но и любые другие файлы(аудио, текстовые) в общем все то что поддерживает браузер google chrome.
На этом данная статья подошла к концу. Подводя итог, скажу. Не смотря на то что filesystem api поддерживается только в google chrome, вам ничто не мешает пользоваться им при написании расширений для браузера chrome. Лично я так и делаю, все очень крутое но поддерживается только в google chrome я использую в своих расширениях.
Вот пример, моего расширения с использованием filesystem api -
https://chrome.google.com/webstore/detail/аудио-плеер/pmgimfodfkeiokcjdgiclpigddakahnb/related?hl=ru. Скачивайте и наслаждайтесь!
Не забывайте подписываться на мою группу в Вконтакте и канал на youtube . Оцените новый формат подачи! С вами был Грибин Андрей, всем удачи и до скорых встреч!