HTML5 nos proporciona una gran variedad de nuevas posibilidades, como dibujar con lienzo, implementar multimedia con las API de audio y video, etc. Una de estas herramientas, que todavía es relativamente nueva, es la API del sistema de archivos. Nos da acceso a una sección de espacio aislado del sistema de archivos local del usuario, ¡lo que nos permite llenar el vacío entre las aplicaciones web y de escritorio! En el tutorial de hoy, repasaremos los conceptos básicos de esta nueva y emocionante API, explorando las tareas más comunes del sistema de archivos. Empecemos!
Ya no necesitamos descargar e instalar un software determinado para poder usarlo. Simplemente un navegador web y una conexión a internet nos permiten utilizar cualquier aplicación web, en cualquier momento, en cualquier lugar y en cualquier plataforma..
En resumen, las aplicaciones web son geniales; pero, en comparación con las aplicaciones de escritorio, todavía tienen una debilidad importante: no tienen una forma de interactuar y organizar los datos en una jerarquía estructurada de carpetas, un sistema de archivos real. Afortunadamente, con la nueva API del sistema de archivos, esto se puede cambiar. Esta API proporciona a las aplicaciones web acceso controlado a un "sandbox" privado del sistema de archivos privado, en el que pueden escribir y leer archivos, crear y listar directorios, etc. Aunque en el momento de escribir esto, solo el navegador Chrome de Google admite la implementación "completa" de la API del sistema de archivos, todavía merece ser estudiado como una forma potente y conveniente de almacenamiento local..
La API del sistema de archivos viene en dos versiones diferentes. La API asíncrona, que es útil para las aplicaciones normales, y la API síncrona, reservada para el uso con trabajadores web. Para los fines de este tutorial, exploraremos exclusivamente la versión asíncrona de la API.
Su primer paso es obtener acceso al sistema de archivos HTML5 solicitando un Archivo local
Objeto del sistema, utilizando el window.requestFileSystem ()
método global:
window.requestFileSystem (tipo, tamaño, successCallback, opt_errorCallback)
No hay forma de que una aplicación web se "rompa" más allá del directorio raíz local.
Como los dos primeros parámetros, especifique la duración y el tamaño del sistema de archivos que desea. UNA PERSISTENTE El sistema de archivos es adecuado para aplicaciones web que desean almacenar datos de usuarios de forma permanente. El navegador no lo eliminará, excepto en la solicitud explícita del usuario. UNA TEMPORAL El sistema de archivos es adecuado para las aplicaciones web que desean almacenar datos en caché, pero aún pueden funcionar si el navegador web elimina el sistema de archivos. El tamaño del sistema de archivos se especifica en bytes y debe ser un límite superior razonable en la cantidad de datos que necesita almacenar.
El tercer parámetro es una función de devolución de llamada que se activa cuando el agente de usuario proporciona con éxito un sistema de archivos. Su argumento es un Sistema de archivos
objeto. Y, por último, podemos agregar una función de devolución de llamada opcional, que se llama cuando se produce un error, o se deniega la solicitud de un sistema de archivos. Su argumento es un Error de archivo
objeto. Aunque este parámetro es opcional, siempre es una buena idea detectar errores para los usuarios, ya que hay una serie de lugares donde las cosas pueden salir mal..
El sistema de archivos obtenido con estas funciones depende del origen del documento que lo contiene. Todos los documentos o aplicaciones web del mismo origen (host, puerto y protocolo) comparten un sistema de archivos. Dos documentos o aplicaciones de diferentes orígenes tienen sistemas de archivos completamente distintos y separados. Un sistema de archivos está restringido a una sola aplicación y no puede acceder a los datos almacenados de otra aplicación. También está aislado del resto de los archivos en el disco duro del usuario, lo cual es bueno: no hay forma de que una aplicación web "se escape" más allá del directorio raíz local o acceda a archivos arbitrarios..
Repasemos un ejemplo:
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem (window.TEMPORARY, 5 * 1024 * 1024, initFS, errorHandler); function initFS (fs) alert ("¡Bienvenido a Filesystem! It's showtime :)"); // Solo para comprobar si todo está bien :) // coloque las funciones que aprenderá más abajo aquí function errorHandler () console.log ('Ocurrió un error');
Esto crea un sistema de archivos temporal con 5MB de almacenamiento. Luego proporciona una función de devolución de llamada exitosa, que utilizaremos para operar nuestro sistema de archivos. Y, por supuesto, también se agrega un controlador de errores, en caso de que algo salga mal. Aquí el errorHandler ()
La función es demasiado genérica. Entonces, si lo desea, puede crear una versión ligeramente optimizada, lo que le da al lector un mensaje de error más descriptivo:
function errorHandler (err) var msg = 'Ocurrió un error:'; switch (err.code) caso FileError.NOT_FOUND_ERR: msg + = 'Archivo o directorio no encontrado'; descanso; caso FileError.NOT_READABLE_ERR: msg + = 'Archivo o directorio no legible'; descanso; caso FileError.PATH_EXISTS_ERR: msg + = 'El archivo o directorio ya existe'; descanso; caso FileError.TYPE_MISMATCH_ERR: msg + = 'Tipo de archivo no válido'; descanso; predeterminado: msg + = 'Error desconocido'; descanso; ; console.log (msg); ;
El objeto del sistema de archivos que obtienes tiene una nombre
(un nombre único para el sistema de archivos, asignado por el navegador) y raíz
Propiedad que se refiere al directorio raíz del sistema de archivos. Esto es un DirectoryEntry
objeto, y puede tener directorios anidados que a su vez están representados por DirectoryEntry
objetos. Cada directorio en el sistema de archivos puede contener archivos, representados por FileEntry
objetos. los DirectoryEntry
objeto define métodos para obtener DirectoryEntry
y FileEntry
objetos por nombre de ruta (opcionalmente crearán nuevos directorios o archivos si especifica un nombre que no existe). DirectoryEntry
también define un createReader ()
método de fábrica que devuelve una DirectoryReader
Objeto para listar los contenidos de un directorio. los FileEntry
clase define un método para obtener el Expediente
Objeto (un Blob) que representa el contenido de un archivo. A continuación, puede utilizar un FileReader
objeto para leer el archivo. FileEntry
define otro método para devolver una FileWriter
Objeto que puedes usar para escribir contenido en un archivo..
Phhew ... suena complicado? No te preocupes Todo se aclarará a medida que avanzamos en los ejemplos a continuación..
Obviamente, lo primero que necesita crear en un sistema de archivos es algunos grupos o directorios. Aunque el directorio raíz ya existe, no desea colocar todos sus archivos allí. Los directorios son creados por el DirectoryEntry
objeto. En el siguiente ejemplo, creamos un directorio, llamado Documentos
, dentro del directorio raíz:
fs.root.getDirectory ('Documents', create: true, function (dirEntry) alert ('Acaba de crear el directorio' + dirEntry.name + '.');, errorHandler);
los getDirectory ()
El método se utiliza tanto para leer como para crear directorios. Como primer parámetro, puede pasar un nombre o una ruta como directorio para buscar o crear. Establecemos el segundo argumento para cierto
, porque estamos intentando crear un directorio, no leer uno existente. Y al final, añadimos un error de devolución de llamada..
Hasta ahora tan bueno. Tenemos un directorio; ahora vamos a agregar un subdirectorio. La función es exactamente la misma con una diferencia: cambiamos el primer argumento de 'Documentos' a 'Documentos / Música'. Suficientemente fácil; pero ¿qué pasa si desea crear una subcarpeta, Cielo
, con dos carpetas principales, Imágenes
y Naturaleza
, dentro de Documentos
¿carpeta? Si escribesDocumentos / Imágenes / Naturaleza / Cielo
'para el argumento de ruta, recibirá un error, porque no puede crear un directorio cuando su principal inmediato no existe. Una solución para esto es crear cada carpeta una por una: Imágenes
dentro Documentos
, Naturaleza
dentro Imágenes
, y entonces Cielo
dentro Naturaleza
. Pero este es un proceso muy lento e inconveniente. Hay una solución mejor: crear una función que creará todas las carpetas necesarias automáticamente.
function createDir (rootDir, carpetas) rootDir.getDirectory (carpetas [0], create: true, function (dirEntry) if (carpetas.length) createDir (dirEntry, Folder.slice (1));, errorHandler); ; createDir (fs.root, 'Documents / Images / Nature / Sky /'. split ('/'));
Con este pequeño truco, todo lo que tenemos que hacer es proporcionar una ruta completa que represente las carpetas que queremos crear. Ahora el Cielo
El directorio se crea con éxito y puede crear otros archivos o directorios dentro de él..
Ahora es el momento de comprobar lo que tenemos en nuestro sistema de archivos. Vamos a crear un DirectoryReader
objeto, y utilizar el readEntries ()
Método para leer el contenido del directorio..
fs.root.getDirectory ('Documents', , function (dirEntry)
var dirReader = dirEntry.createReader (); dirReader.readEntries (función (entradas)
para (var i = 0; i < entries.length; i++) var entry = entries[i]; if (entry.isDirectory) console.log('Directory: ' + entry.fullPath); else if (entry.isFile) console.log('File: ' + entry.fullPath); , errorHandler); , errorHandler);
En el código de arriba, el esdirectorio
y isFile
Las propiedades se utilizan para obtener una salida diferente para directorios y archivos, respectivamente. Además, utilizamos el ruta completa
propiedad para obtener la ruta completa de la entrada, en lugar de su nombre solamente.
Hay dos formas de eliminar un DirectoryEntry
desde el sistema de archivos: retirar()
y removeRecursively ()
. El primero elimina un directorio dado solo si está vacío. De lo contrario, recibirás un error..
fs.root.getDirectory ('Documents / Music', , function (dirEntry) dirEntry.remove (function () console.log ('Directorio eliminado con éxito.');, errorHandler);, errorHandler);
Si el Música
La carpeta tiene archivos dentro, entonces necesita usar el segundo método, que borra recursivamente el directorio y todo su contenido..
fs.root.getDirectory ('Documents / Music', , function (dirEntry) dirEntry.removeRecursively (function () console.log ('Directorio eliminado exitosamente.');, errorHandler);, errorHandler);
Ahora que sabemos cómo crear directorios, es hora de rellenarlos con archivos!
El siguiente ejemplo crea un vacío test.txt
en el directorio raíz:
fs.root.getFile ('test.txt', create: true, exclusive: true, function (fileEntry) alert ('Un archivo' + fileEntry.name + 'se creó correctamente.');, errorHandler) ;
El primer argumento para Obtener el archivo()
Puede ser una ruta absoluta o relativa, pero debe ser válida. Por ejemplo, es un error intentar crear un archivo cuando su principal inmediato no existe. El segundo argumento es un objeto literal, que describe el comportamiento de la función si el archivo no existe. En este ejemplo, crear: verdadero
crea el archivo si no existe y emite un error si lo hace (exclusivo: verdadero
). De lo contrario, si crear: falso
, el archivo es simplemente recuperado y devuelto.
Sin embargo, tener un archivo vacío no es muy útil; Así que vamos a añadir algo de contenido dentro. Podemos usar el FileWriter
objetar por esto.
fs.root.getFile ('test.txt', create: false, function (fileEntry) fileEntry.createWriter (function (fileWriter) window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = new BlobBuilder (); bb.append ('¡La API del sistema de archivos es increíble!'); fileWriter.write (bb.getBlob ('text / plain'));, errorHandler);, errorHandler);
Arriba, recuperamos el test.txt
archivo, y crear un FileWriter
objeto para ello. Luego le agregamos contenido creando un nuevo BlobBuilder
objeto y usando el escribir()
método de FileWriter
.
Vocación Obtener el archivo()
solo recupera un FileEntry
. No devuelve el contenido del archivo. Entonces, si queremos leer el contenido del archivo, necesitamos usar el Expediente
objeto y el FileReader
objeto.
fs.root.getFile ('test.txt', , function (fileEntry) fileEntry.file (function (file) var reader = new FileReader (); reader.onloadend = function (e) alert (this. resultado);; reader.readAsText (file);, errorHandler);, errorHandler);
Hemos escrito algo de contenido en nuestro archivo, pero ¿qué pasa si deseo agregar más en una fecha posterior? Para adjuntar datos a un archivo existente, la FileWriter
Se usa una vez más. Podemos reposicionar el escritor al final del archivo, usando el buscar()
método. buscar
acepta un byte offset como argumento y establece la posición del escritor del archivo en ese offset.
fs.root.getFile ('test.txt', create: false, function (fileEntry) fileEntry.createWriter (function (fileWriter) fileWriter.seek (fileWriter.length); window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = new BlobBuilder (); bb.append ('Sí, es!'); fileWriter.write (bb.getBlob ('text / plain'));, errorHandler);, errorHandler) ;
Para eliminar un archivo del sistema de archivos, simplemente llame entry.remove ()
. El primer argumento de este método es una función de devolución de llamada de parámetro cero, que se llama cuando el archivo se elimina con éxito. El segundo es una devolución de llamada de error opcional si se produce algún error.
fs.root.getFile ('test.txt', create: false, function (fileEntry) fileEntry.remove (function () console.log ('El archivo se eliminó con éxito.');, errorHandler);, errorHandler);
FileEntry
y DirectoryEntry
comparte los mismos métodos API para copiar, mover y renombrar entradas. Hay dos métodos que puede utilizar para estas operaciones: copiar a()
y mover a()
. Ambos aceptan exactamente los mismos parámetros:
copyTo (parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback); moveTo (parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback);
El primer parámetro es la carpeta principal para mover / copiar la entrada en. El segundo es un nuevo nombre opcional para dar la entrada movida / copiada, que en realidad se requiere cuando copia una entrada en la misma carpeta; De lo contrario obtendrá un error. Los parámetros tercero y cuarto fueron explicados previamente..
Repasemos algunos ejemplos simples. En el siguiente, copiamos el archivo. test.txt
desde el raíz
al Documentos
directorio.
function copy (currDir, srcEntry, destDir) currDir.getFile (srcEntry, , function (fileEntry) currDir.getDirectory (destDir, , function (dirEntry) fileEntry.copyTo (dirEntry);), errorHandler); , errorHandler); copia (fs.root, 'test.txt', 'Documentos /');
El siguiente ejemplo se mueve. test.txt
a Documentos
, En lugar de copiarlo:
function move (currDir, srcEntry, dirName) currDir.getFile (srcEntry, , function (fileEntry) currDir.getDirectory (dirName, , function (dirEntry) fileEntry.moveTo (dirEntry);, errorHandler); , errorHandler); mover (fs.root, 'test.txt', 'Documentos /');
El siguiente ejemplo renombra test.txt
a texto.txt
:
function rename (currDir, srcEntry, newName) currDir.getFile (srcEntry, , function (fileEntry) fileEntry.moveTo (currDir, newName);, errorHandler); renombrar (fs.root, 'test.txt', 'text.txt');
En este tutorial introductorio, solo hemos arañado la superficie de las diferentes interfaces del sistema de archivos. Si desea obtener más información y profundizar en la API del sistema de archivos, debe consultar las especificaciones de W3C:
Ahora que tiene una comprensión básica de qué es la API del sistema de archivos y cómo se puede usar, debería ser mucho más fácil entender la documentación de la API, que puede ser un poco confusa a primera vista..
La API del sistema de archivos es una tecnología poderosa y fácil de usar, que brinda a los desarrolladores web toda una serie de nuevas posibilidades al crear aplicaciones web. Es cierto que todavía es bastante nuevo y no está ampliamente soportado por todos los navegadores principales, pero esto ciertamente cambiará en el futuro. Usted también podría obtener una ventaja!