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 elBlob
con un mime type válido de audiopictures
sólo acepta elBlob
con un mime type válido de imagenvideos
sólo acepta elBlob
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:
DeviceStorageChangeEvent.reason
que da la razón del cambio (created
,modified
odeleted
)DeviceStorageChangeEvent.path
que brinda la ruta completa del archivo afectado por el cambio.
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 |