Device Storage API

by 1 contributor:

No estándar

This API is available on Firefox OS for privileged or certified applications only.

Resumen

La API de Device Storage es usada para acceder al sistema de archivos dentro de una aplicación Web. Acceder al sistema de archivos puede ser muy susceptible, por ese motivo, esta API está disponible sólo para aplicaciones con privilegios.

Nota: El acceso a un dispositivo de almacenamiento es lento debido a la limitación en el nivel físico. En muchos casos puede resultar más rápido usar una base de datos IndexedDB para almacenar archivos en lugar del dispositivo de almacenamiento físico.

Acceso a un almacenamiento

Punto de entrada

Es posible acceder a un área de almacenamiento usando el método navigator.getDeviceStorage(). Acepta un parámetro de cadena que representa el nombre del alamacenamiento al cual se quiere tener acceso. El método devuelve un objeto DeviceStorage que es usado para acceder al área de almacenamiento relacionada.

Firefox OS proporciona el siguiente nombre de almacenamiento:

  • apps: Esta área de almacenamiento es usada para almacenar los datos de usuario necesarios para las aplicaciones. Como se trata de datos confidenciales, acceder a esta área de almacenamiento requiere algunos privilegios extra y está disponible sólamente para aplicaciones certificadas.
  • music: Esta es el área de almacenamiento donde son almacenados música y sonidos.
  • pictures: Esta es el área de almacenamiento donde se almacenan las fotos.
  • sdcard: Esta es el área de almacenamiento que brinda acceso al SDCard del dispositivo.
  • videos: Esta es el área de almacenamiento donde son almacenados los videos.
var pics = navigator.getDeviceStorage('pictures');

Para ser capaz de usar cada una de las áreas de almacenamiento, la aplicación debe declararlas en su archivo de manifiesto. Por ejemplo, si la aplicación quiere acceder al área de almacenamiento de la sdcard, debe tener el permiso "device-storage:sdcard" en su manifiesto.

"permissions": {
  "device-storage:videos":{ "access": "readonly" },
  "device-storage:pictures":{ "access": "readwrite" }
}

El uso de un almacenamiento

Una vez que una aplicación tenga acceso de un área de almacenamiento, es posible agregar, obtener y eliminar archivos dentro del área.

Agregar un archivo

Se puede agregar una archivo utilizando el método addNamed o add. La primera permite establecer un nombre explícito para guardar un archivo mientras que la segunda crea un nombre automáticamente cuando se guarda el archivo. Ambos nombres son asíncronos y devuelven un objeto DOMRequest para manejar el success o error de la operación. Esto debe considerar importante que tanto agregar, escribir y leer archivos en un soporte físico es un proceso lento.

Esos dos métodos esperan un Blob como su primer parámetro. Este objeto será convertido en un archivo y almacenado. Al crear un objeto Blob, es obligatorio darle un tipo. Este tipo, que es un mime type, es importante porque algunas áreas de almacenamiento tienen restricciones basadas en el tipo:

  • music sólo acepta el Blob con un mime type válido de audio
  • pictures sólo acepta el Blob con un mime type válido de imagen
  • videos sólo acepta el Blob con un mime type válido de video
var sdcard = navigator.getDeviceStorage("sdcard");
var file   = new Blob(["Este es un archivo de texto."], {type: "text/plain"});

var request = sdcard.addNamed(file, "mi-archivo.txt");

request.onsuccess = function () {
  var name = this.result.name;
  console.log('El archivo "' + name + '" se escribió correctamente en el área de almacenamiento sdcard');
}

// Un error suele producirse si un archivo con el mismo nombre ya existe
request.onerror = function () {
  console.warn('No se puede escribir el archivo: ' + this.error);
}

Nota: El repositorio en un área de almacenamiento está implícito. No es posible crear explícitamente un repositorio vacío. Si quiere usar una estructura de repositorio tiene que hacerlo parte del nombre del archivo a almacenar. Así que si quiere almacenar el archivo bar dentro del repositorio foo, tiene que usar el método addNamed con el nombre completo de la ruta del archivo addNamed(blob, "foo/bar"). Esto también se aplica cuando quiere recuperar un archivo con su nombre (véase más adelante).

Como el archivo es agregado en un área de almacenamiento restringido por razones de seguridad, un nombre de ruta de archivo no puede empezar con "/" ni "../" (y "./" no tiene sentido).

Obtener un archivo

Se puede recuperar un archivo de dos maneras: usando su nombre o iterando toda la lista de archivos.

La manera más fácil es recuperar un archivo por su nombre usando los métodos get y getEditable. La primera proporciona un objeto File (que actúa como un archivo de sólo lectura) mientras que la segunda proporciona un objeto FileHandle (que permite actualizar el archivo subyacente). Ambos métodos son asíncronos y devuelven un objeto DOMRequest para manejar el success o error de la operación.

var sdcard = navigator.getDeviceStorage('sdcard');

var request = sdcard.get("mi-archivo.txt");

request.onsuccess = function () {
  var file = this.result;
  console.log("Obtenido el archivo: " + file.name);
}

request.onerror = function () {
  console.warn("No se puede obtener el archivo: " + this.error);
}

La otra forma de recuperar archivos es explorar el contenido del área de almacenamiento. Esto es posible usando los métodos enumerate y enumerateEditable. El primero proporciona objetos File mientras que el segundo proporciona objetos FileHandle. Ambos métodos son asíncronos y devuelven un objeto DOMCursor para recorrer a lo largo de la lista de archivos. Un DOMCursor es nada menos que un objeto DOMRequest con potencia extra para recorrer a lo largo de la lista de cosas (archivos en ese caso) en forma asíncrona.

var pics = navigator.getDeviceStorage('pictures');

// Exploremos todas las imágenes disponibles
var cursor = pics.enumerate();

cursor.onsuccess = function () {
  var file = this.result;
  console.log("Archivo encontrado: " + file.name);

  // Una vez que encontremos el archivo verifiquemos si hay otros resultados
  if (!this.done) {
    // Entonces nos movemos al siguiente resultado, que llama al cursor
    // success con el siguiente archivo como resultado.
    this.continue();
  }
}

cursor.onerror = function () {
  console.warn("Archivo no encontrado: " + this.error);
}

Es posible limitar el número de resultados pasando dos parámetros opcionales a los m´todos enumerate y enumerateEditable.

El primer parámetro puede ser una cadena que representa una subcarpeta para buscar dentro.

El segundo parámetro puede ser un objeto con una propiedad since, que permite limitar la búsqueda a un determinado periodo de tiempo.

var pics = navigator.getDeviceStorage('pictures');

// Recuperamos fotos de la semana pasada
var param = {
  since: new Date((+new Date()) - 7*24*60*60*1000)
}

var cursor = pics.enumerate(param);

cursor.onsuccess = function () {
  var file = this.result;
  console.log("Foto tomada en: " + file.lastModifiedDate);

  if (!this.done) {
    this.continue();
  }
}

Eliminar un archivo

Un archivo se puede eliminar del área de almacenamiento usando simplemente el método delete. Este método sólo necesita el nombre del archivo a eliminar. Como todos los demás métodos de la interfaz DeviceStorage, este también es asíncrono y devuelve un objeto DOMRequest para manejar el success o error de la operación.

var sdcard = navigator.getDeviceStorage('sdcard');

var request = sdcard.delete("mi-archivo.txt");

request.onsuccess = function () {
  console.log("Archivo eliminado");
}

request.onerror = function () {
  console.log("No se puede eliminar el archivo: " + this.error);
}

Información de almacenamiento

Además de acceder a los archivos, un área de almacenamiento proporciona algunos métodos para obtener fácilmente información importante.

Espacio disponible

Una de las cosas más importantes a saber cuando se almacenan archivos en un dispositivo es la cantidad de espacio disponible. La interfaz DeviceStorage proporciona tres funciones útiles dedicadas al espacio:

  • freeSpace() para obtener la cantidad de espacio libre disponible para almacenar nuevos archivos;
  • usedSpace() para obtener la cantidad de espacio utilizado para almacenar archivos;
  • available() para obtener la cantidad total de espacio dedicado al área de almacenamiento.

Como esos métodos son asíncronos, devuelven un objeto DOMRequest para manejar los success o error de la operación.

var videos = navigator.getDeviceStorage('videos');

var request = videos.usedSpace();

request.onsuccess = function () {
  // El resultado es expresado en bytes, permite convertirlo en megabytes
  var size = this.result / 1000000;

  console.log("Los videos en tu dispositivo ocupan un total de " + size.toFixed(2) + "Mb de espacio.");
}

request.onerror = function () {
  console.warn("No se puede obtener el espacio utilizado por videos: " + this.error);
}

Escuchar los cambios

Como muchas aplicaciones pueden usar un mismo área de almacenamiento al mismo tiempo, a veces es útil para una aplicación ser consciente de un cambio en ese área de almacenamiento. También es útil para una aplicación que quiere realizar la acción asíncrona sin la retransmisión de todos los objetos DOMRequest que devuelven por cada método de la interfaz DeviceStorage.

Para ese fin, un evento change se activa cada vez que se crea, modifica o elimina un archivo. Este evento se puede capturar usando la propiedad onchange o el método addEventListener(). El controlador de eventos recibe un objeto DeviceStorageChangeEvent que es un objeto Event regular con dos propiedades adicionales:

var sdcard = navigator.getDeviceStorage('sdcard');

sdcard.onchange = function (change) {
  var reason = change.reason;
  var path   = change.path;

  console.log('El archivo "' + path + '" ha sido ' + reason);
}

Especificación

No es parte de ninguna especificación.

Compatibilidad del navegador

Característica Chrome Firefox (Gecko) Internet Explorer Opera Safari
Soporte básico ? ? Not supported Not supported Not supported
Característica Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Soporte básico ? ? Not supported Not supported Not supported

Véase también

Etiquetas y colaboradores del documento

Contributors to this page: elfoxero
Última actualización por: elfoxero,