funciona - html5 video controls
API de archivo HTML5 que descarga el archivo del servidor y lo guarda en sandbox (3)
Estoy tratando de entender la API HTML5. Estoy diseñando la aplicación web donde el cliente del navegador necesita descargar varios archivos del servidor; el usuario realizará algo con los archivos descargados y la aplicación que deberá guardar el estado en el disco duro del usuario. Entiendo que el navegador puede guardar estos archivos solo en su caja de arena, lo que está bien siempre que el usuario pueda recuperar esos archivos la segunda vez que inicie la aplicación. ¿Debo usar BlobBuilder o FileSaver? Estoy un poco perdido aquí.
Le mostraré cómo descargar archivos con XMLHttpRequest Level 2 y guardarlos con la API FileSystem o con la interfaz FileSaver .
Descargando archivos
Para descargar un archivo, utilizará XMLHttpRequest Level 2 (también conocido como XHR2), que admite solicitudes de origen cruzado, carga de eventos de progreso y carga / descarga de datos binarios. En la publicación " Nuevos trucos en XMLHttpRequest2 " hay muchos ejemplos de uso de XHR2.
Para descargar un archivo como un blob, todo lo que tiene que hacer es especificar el tipo de responseType
en "blob". También puede utilizar los tipos "texto", "arraybuffer" o "documento". La siguiente función descarga el archivo en la url
y lo envía a la devolución de llamada correcta:
function downloadFile(url, success) {
var xhr = new XMLHttpRequest();
xhr.open(''GET'', url, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (success) success(xhr.response);
}
};
xhr.send(null);
}
La devolución de llamada success
recibirá como argumento una instancia de Blob que luego se puede modificar y guardar y / o cargar en un servidor.
Guardar archivos con la API FileSystem
Como indica el sitio Can i use ... , no hay muchos navegadores compatibles con FileSystem API. Para Firefox hay una explicación para la falta de soporte. Por lo tanto, tendrás que usar Chrome para hacer esto.
Primero tendrá que solicitar un espacio de almacenamiento, puede ser temporal o persistente. Probablemente querrá tener un almacenamiento persistente, en este caso tendrá que solicitar una cuota de espacio de almacenamiento por adelantado ( algunos datos ):
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.storageInfo = window.storageInfo || window.webkitStorageInfo;
// Request access to the file system
var fileSystem = null // DOMFileSystem instance
, fsType = PERSISTENT // PERSISTENT vs. TEMPORARY storage
, fsSize = 10 * 1024 * 1024 // size (bytes) of needed space
;
window.storageInfo.requestQuota(fsType, fsSize, function(gb) {
window.requestFileSystem(fsType, gb, function(fs) {
fileSystem = fs;
}, errorHandler);
}, errorHandler);
Ahora que tiene acceso al sistema de archivos, puede guardar y leer archivos desde él. La siguiente función puede guardar un blob en la ruta especificada en el sistema de archivos:
function saveFile(data, path) {
if (!fileSystem) return;
fileSystem.root.getFile(path, {create: true}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.write(data);
}, errorHandler);
}, errorHandler);
}
Un para leer un archivo por su ruta:
function readFile(path, success) {
fileSystem.root.getFile(path, {}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
if (success) success(this.result);
};
reader.readAsText(file);
}, errorHandler);
}, errorHandler);
}
Además del método readAsText
, de acuerdo con la API FileReader puede llamar a readAsArrayBuffer
y readAsDataURL
.
Usando el FileSaver
La publicación " Guardar archivos generados en el lado del cliente " explica muy bien el uso de esta API. Es posible que algunos navegadores necesiten FileSaver.js para tener la interfaz saveAs
.
Si lo usa junto con la función downloadFile
, podría tener algo como esto:
downloadFile(''image.png'', function(blob) {
saveAs(blob, "image.png");
});
Por supuesto, tendría más sentido si el usuario pudiera visualizar la imagen, manipularla y luego guardarla en su disco.
Manejador de errores
Solo para cumplir el ejemplo:
function errorHandler(e) {
var msg = '''';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = ''QUOTA_EXCEEDED_ERR'';
break;
case FileError.NOT_FOUND_ERR:
msg = ''NOT_FOUND_ERR'';
break;
case FileError.SECURITY_ERR:
msg = ''SECURITY_ERR'';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = ''INVALID_MODIFICATION_ERR'';
break;
case FileError.INVALID_STATE_ERR:
msg = ''INVALID_STATE_ERR'';
break;
default:
msg = ''Unknown Error'';
break;
};
console.log(''Error: '' + msg);
}
Enlaces útiles
Mi truco es simplemente agregar IFRAME con un atributo "src" que apunta a sus múltiples descargas. El sitio del servidor debe enviar los archivos con un encabezado de "disposición: adjunto" y luego el cliente intentará almacenar el archivo localmente. El único "problema" es que los IFRAME permanecerán en su árbol DOM como residuos hasta que el usuario abandone o vuelva a cargar la página. Haz el IFRAME invisible (por ejemplo, ancho = 0; altura = 0;) ¡y estás listo para ir! Todos los navegadores.
Si solo admite navegadores HTML5, hay un atributo de "descarga" que puede utilizar. Más detalles aquí: http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download