API de Filesystem

El API se divide en varios temas:

  • lectura y manipulación de archivos (File/Blob, FileList, FileReader),
  • creación y escritura (BlobBuilder, FileWriter),
  • acceso a sistemas de archivos y directorios (DirectoryReader, FileEntry/DirectoryEntry, LocalFileSystem).

Solicitud de un sistema de archivos

Una aplicación web puede solicitar acceso al sistema de archivos de prueba con window.requestFileSystem():

window.requestFileSystem(type, size, successCallback, opt_errorCallback);

  • type: Indica si el almacenamiento de archivos debe ser permanente. Los valores que se pueden utilizar son window.TEMPORARY y window.PERSISTENT. Los datos almacenados con el tipo TEMPORARY se pueden eliminar a elección del navegador. Los datos almacenados con el tipo PERSISTENT no se pueden borrar a menos que el usuario o la aplicación lo autoricen expresamente y requieren que el usuario otorgue espacio de almacenamiento a la aplicación.
  • size: Indica el espacio (en bytes) de almacenamiento que necesitará la aplicación.
  • successCallback. Indica la devolución de llamada que se activa cuando se autoriza el acceso a un sistema de archivos. Su argumento es un objeto FileSystem.
  • opt_errorCallback: Corresponde a una devolución de llamada opcional para la gestión de errores o para los casos en los que se deniega la solicitud de acceso al sistema de archivos. Su argumento es un objeto FileError.

Cómo crear un archivo

Para buscar o crear archivos, se puede utilizar el método getFile() de la interfaz DirectoryEntry del sistema de archivos. Una vez que se ha solicitado un sistema de archivos, se transmite a la devolución de llamada de operación correcta un objeto FileSystem que contiene una interfaz DirectoryEntry (fs.root) que señala al directorio raíz del sistema de archivos de la aplicación.

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
function onInitFs(fs) {
    fs.root.getFile('log.txt', {create: true, exclusive: true}, function(fileEntry) {
        // fileEntry.isFile === true
        // fileEntry.name == 'log.txt'
        // fileEntry.fullPath == '/log.txt'
  }, errorHandler);
}

Una vez que se ha solicitado el sistema de archivos, se transmite un objeto FileSystem al controlador de operación correcta. Dentro de la devolución de llamada, se puede solicitar fs.root.getFile() indicando el nombre del archivo que se va a crear. Se puede especificar una ruta absoluta o relativa, pero debe ser una ruta válida. Por ejemplo, es un error intentar crear un archivo cuyo elemento inmediatamente anterior no exista. El segundo argumento de getFile() es una cadena literal de objeto que describe el comportamiento que debe tener la función si el archivo no existe. En este ejemplo, create: true hace que se cree el archivo si no existe y que se genere un error en caso contrario (exclusive: true). Por su parte, create: false hace que el archivo simplemente se extraiga y se muestre. En ambos casos, el contenido del archivo no se sobrescribe, ya que solo se está obteniendo una entrada de referencia al archivo en cuestión.

Cómo leer un archivo por nombre

El código que aparece a continuación permite recuperar el archivo "log.txt", leer su contenido con el API FileReader e incorporarlo a una nueva área de texto (<textarea>) en la página. Si el archivo "log.txt" no existe, se genera un error.

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
function onInitFs(fs) {
    fs.root.getFile('log.txt', {}, function(fileEntry) {
        fileEntry.file(function(file) {
            var reader = new FileReader();
            reader.onloadend = function(e) {
                var txtArea = document.createElement('textarea');
                txtArea.value = this.result;
                document.body.appendChild(txtArea);
            };
            reader.readAsText(file);
        }, errorHandler);
    }, errorHandler);
}

Cómo escribir en un archivo

El código que aparece a continuación permite crear un archivo vacío llamado "log.txt" (en caso de que no exista) y escribir en él el texto "Lorem Ipsum".

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
function onInitFs(fs) {
    fs.root.getFile('log.txt', {create: true}, function(fileEntry) {
        // Create a FileWriter object for our FileEntry (log.txt).
        fileEntry.createWriter(function(fileWriter) {
        fileWriter.onwriteend = function(e) {
            console.log('Write completed.');
        };
        fileWriter.onerror = function(e) {
            console.log('Write failed: ' + e.toString());
        };
        // Create a new Blob and write it to log.txt.
        var bb = new BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
        bb.append('Lorem Ipsum');
        fileWriter.write(bb.getBlob('text/plain'));
        }, errorHandler);
    }, errorHandler);
}

Esta vez, se utiliza el método createWriter() de FileEntry para obtener un objeto FileWriter. Dentro de la devolución de llamada de operación correcta, se definen controladores para los eventos error y writeend. Para escribir los datos del texto en el archivo, se crea un objeto Blob, se le añade texto y se transmite el objeto a FileWriter.write().

Cómo añadir datos a un archivo

El código que aparece a continuación permite añadir el texto "Hello World" al final del archivo de registro. Si el archivo no existe, se genera un error.

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
function onInitFs(fs) {
    fs.root.getFile('log.txt', {create: false}, function(fileEntry) {
       // Create a FileWriter object for our FileEntry (log.txt).
           fileEntry.createWriter(function(fileWriter) {
               fileWriter.seek(fileWriter.length);  // Start write position at EOF.
               // Create a new Blob and write it to log.txt.
               var bb = new BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
               bb.append('Hello World');
               fileWriter.write(bb.getBlob('text/plain'));
            }, errorHandler);
    }, errorHandler);
}

Cómo eliminar un archivo

El código que aparece a continuación permite eliminar el archivo "log.txt".

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
    fs.root.getFile('log.txt', {create: false}, function(fileEntry) {
        fileEntry.remove(function() {
            console.log('File removed.');
        }, errorHandler);
    }, errorHandler);
}, errorHandler);

Cómo copiar entradas, cambiarles el nombre y moverlas

Las interfaces FileEntry y DirectoryEntry comparten algunas operaciones.

Cómo copiar una entrada

Tanto FileEntry como DirectoryEntry cuentan con el método copyTo() para la duplicación de entradas. Este método permite hacer una copia recurrente en diferentes carpetas.

El código del ejemplo que aparece a continuación permite copiar el archivo "me.png" de un directorio en otro:

function copy(cwd, src, dest) {
    cwd.getFile(src, {}, function(fileEntry) {
        cwd.getDirectory(dest, {}, function(dirEntry) {
            fileEntry.copyTo(dirEntry);
        }, errorHandler);
    }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
    copy(fs.root, '/folder1/me.png', 'folder2/mypics/');
}, errorHandler);

Cómo mover una entrada o cambiarle el nombre

El método moveTo() de FileEntry y DirectoryEntry permite mover archivos y directorios y cambiarles el nombre. El primer argumento especifica el directorio principal al que se debe mover el archivo y el segundo argumento indica un nuevo nombre opcional para el archivo. Si no se especifica un nombre nuevo, se utilizará el nombre original del archivo.

El código de ejemplo que aparece a continuación permite sustituir el nombre del archivo "me.png" por "you.png" sin mover el archivo:

function rename(cwd, src, newName) {
    cwd.getFile(src, {}, function(fileEntry) {
        fileEntry.moveTo(cwd, newName);
    }, errorHandler);
}
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
    rename(fs.root, 'me.png', 'you.png');
}, errorHandler);

El código de ejemplo que aparece a continuación permite mover el archivo "me.png" (ubicado en el directorio raíz) a una carpeta llamada "newfolder".

function move(src, dirName) {
    fs.root.getFile(src, {}, function(fileEntry) {
        fs.root.getDirectory(dirName, {}, function(dirEntry) {
            fileEntry.moveTo(dirEntry);
        }, errorHandler);
    }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
    move('/me.png', 'newfolder/');
}, errorHandler);