Quiero mostrar archivos de OpenOffice , .odt y .odp en el lado del cliente usando un navegador web.
Estos archivos son archivos comprimidos. Usando Ajax, puedo obtener estos archivos del servidor, pero son archivos comprimidos. Tengo que descomprimirlos usando JavaScript , he intentado usar inflate.js, http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt , pero sin éxito.
¿Cómo puedo hacer esto?
javascript
zip
unzip
usuario69260
fuente
fuente
Respuestas:
Escribí un descomprimidor en Javascript. Funciona.
Se basa en el lector de archivos binarios de Andy GP Na y en alguna lógica de inflado RFC1951 de notmasteryet . Agregué la clase ZipFile.
ejemplo de trabajo:
http://cheeso.members.winisp.net/Unzip-Example.htm (enlace muerto)
La fuente:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (enlace muerto)
NB : los enlaces están muertos; Pronto encontraré un nuevo anfitrión.
En la fuente se incluye una página de demostración ZipFile.htm y 3 scripts distintos, uno para la clase zipfile, uno para la clase inflar y otro para una clase de lector de archivos binarios. La demostración también depende de jQuery y jQuery UI. Si acaba de descargar el archivo js-zip.zip, todas las fuentes necesarias están allí.
Así es como se ve el código de la aplicación en Javascript:
// In my demo, this gets attached to a click event. // it instantiates a ZipFile, and provides a callback that is // invoked when the zip is read. This can take a few seconds on a // large zip file, so it's asynchronous. var readFile = function(){ $("#status").html("<br/>"); var url= $("#urlToLoad").val(); var doneReading = function(zip){ extractEntries(zip); }; var zipFile = new ZipFile(url, doneReading); }; // this function extracts the entries from an instantiated zip function extractEntries(zip){ $('#report').accordion('destroy'); // clear $("#report").html(''); var extractCb = function(id) { // this callback is invoked with the entry name, and entry text // in my demo, the text is just injected into an accordion panel. return (function(entryName, entryText){ var content = entryText.replace(new RegExp( "\\n", "g" ), "<br/>"); $("#"+id).html(content); $("#status").append("extract cb, entry(" + entryName + ") id(" + id + ")<br/>"); $('#report').accordion('destroy'); $('#report').accordion({collapsible:true, active:false}); }); } // for each entry in the zip, extract it. for (var i=0; i<zip.entries.length; i++) { var entry = zip.entries[i]; var entryInfo = "<h4><a>" + entry.name + "</a></h4>\n<div>"; // contrive an id for the entry, make it unique var randomId = "id-"+ Math.floor((Math.random() * 1000000000)); entryInfo += "<span class='inputDiv'><h4>Content:</h4><span id='" + randomId + "'></span></span></div>\n"; // insert the info for one entry as the last child within the report div $("#report").append(entryInfo); // extract asynchronously entry.extract(extractCb(randomId)); } }
La demostración funciona en un par de pasos: el
readFile
fn se activa con un clic y crea una instancia de un objeto ZipFile, que lee el archivo zip. Hay una devolución de llamada asincrónica para cuando se completa la lectura (generalmente ocurre en menos de un segundo para cremalleras de tamaño razonable); en esta demostración, la devolución de llamada se mantiene en la variable local doneReading, que simplemente llamaextractEntries
, que simplemente descomprime ciegamente todo el contenido de la archivo zip. En una aplicación real, probablemente elegiría algunas de las entradas para extraer (permitir que el usuario seleccione o elija una o más entradas mediante programación, etc.).El
extractEntries
fn itera sobre todas las entradas y llamaextract()
a cada una, pasando una devolución de llamada. La descompresión de una entrada lleva tiempo, tal vez 1 so más por cada entrada en el archivo zip, lo que significa que la asincronía es apropiada. La devolución de llamada de extracción simplemente agrega el contenido extraído a un acordeón jQuery en la página. Si el contenido es binario, se formatea como tal (no se muestra).Funciona, pero creo que la utilidad es algo limitada.
Por un lado: es muy lento. Tarda ~ 4 segundos en descomprimir el archivo 140k AppNote.txt de PKWare. La misma descompresión se puede realizar en menos de .5 segundos en un programa .NET.EDITAR : El Javascript ZipFile se descomprime considerablemente más rápido que esto ahora, en IE9 y en Chrome. Sigue siendo más lento que un programa compilado, pero es bastante rápido para el uso normal del navegador.Por otro: no hace streaming. Básicamente, absorbe todo el contenido del archivo zip en la memoria. En un entorno de programación "real", podría leer solo los metadatos de un archivo zip (por ejemplo, 64 bytes por entrada) y luego leer y descomprimir los demás datos como desee. No hay forma de hacer IO así en javascript, hasta donde yo sé, por lo tanto, la única opción es leer todo el zip en la memoria y hacer acceso aleatorio en él. Esto significa que impondrá demandas irrazonables a la memoria del sistema para archivos zip grandes. No es tanto un problema para un archivo zip más pequeño.
Además: no maneja el archivo zip "caso general" - hay muchas opciones zip que no me molesté en implementar en el descomprimidor - como cifrado ZIP, cifrado WinZip, zip64,
nombres de archivo codificados en UTF-8,etc. en. ( EDITAR : ahora maneja nombres de archivo codificados en UTF-8). Sin embargo, la clase ZipFile maneja lo básico. Algunas de estas cosas no serían difíciles de implementar. Tengo una clase de cifrado AES en Javascript; que podría integrarse para admitir el cifrado. La compatibilidad con Zip64 probablemente sería inútil para la mayoría de los usuarios de Javascript, ya que está destinada a admitir archivos zip> 4gb, no es necesario extraerlos en un navegador.Tampoco probé el caso para descomprimir contenido binario. Ahora mismo descomprime el texto. Si tiene un archivo binario comprimido, necesitará editar la clase ZipFile para manejarlo correctamente. No descubrí cómo hacerlo limpiamente.Ahora también hace archivos binarios.EDITAR - Actualicé la biblioteca de descomprimir JS y la demostración. Ahora hace archivos binarios, además de texto. Lo he hecho más resistente y más general: ahora puede especificar la codificación que se usará al leer archivos de texto. También se amplía la demostración: muestra cómo descomprimir un archivo XLSX en el navegador, entre otras cosas.
Entonces, aunque creo que tiene una utilidad e interés limitados, funciona. Supongo que funcionaría en Node.js.
fuente
Estoy usando zip.js y parece ser bastante útil. ¡Vale la pena echarle un vistazo!
Consulte la demostración de Unzip , por ejemplo.
fuente
pako.inflate(binaryData, { to: 'string' })
Encontré jszip bastante útil. Los he usado hasta ahora solo para leer, pero también tienen capacidades de creación / edición.
En cuanto al código, se parece a esto
var new_zip = new JSZip(); new_zip.load(file); new_zip.files["doc.xml"].asText() // this give you the text in the file
Una cosa que noté es que parece que el archivo tiene que estar en formato de flujo binario (lea usando el .readAsArrayBuffer de FileReader (), de lo contrario, recibía errores que indicaban que podría tener un archivo zip corrupto
Editar: Nota de la guía de actualización 2.xa 3.0.0 :
Gracias user2677034
fuente
Si también necesita admitir otros formatos o simplemente necesita un buen rendimiento, puede usar esta biblioteca de WebAssembly
está basado en promesas, utiliza WebWorkers para subprocesos y la API es en realidad un módulo ES simple
fuente
Escribí "Herramientas binarias para JavaScript", un proyecto de código abierto que incluye la capacidad de descomprimir, descomprimir y descomprimir: https://github.com/codedread/bitjs
Utilizado en mi lector de cómics: https://github.com/codedread/kthoom (también de código abierto).
HTH!
fuente
El ejemplo de código se da en el sitio del autor . Puede utilizar babelfish para traducir los textos (del japonés al inglés).
Por lo que entiendo japonés, este código de inflado postal está destinado a decodificar datos ZIP (flujos), no archivos ZIP.
fuente
También escribí una clase para eso. http://blog.another-d-mention.ro/programming/read-load-files-from-zip-in-javascript/ Puede cargar activos básicos como javascript / css / images directamente desde el zip usando métodos de clase. Espero eso ayude
fuente
Si alguien está leyendo imágenes u otros archivos binarios de un archivo zip alojado en un servidor remoto, puede usar el siguiente fragmento para descargar y crear un objeto zip usando la biblioteca jszip .
// this function just get the public url of zip file. let url = await getStorageUrl(path) console.log('public url is', url) //get the zip file to client axios.get(url, { responseType: 'arraybuffer' }).then((res) => { console.log('zip download status ', res.status) //load contents into jszip and create an object jszip.loadAsync(new Blob([res.data], { type: 'application/zip' })).then((zip) => { const zipObj = zip $.each(zip.files, function (index, zipEntry) { console.log('filename', zipEntry.name) }) })
Ahora, usando zipObj, puede acceder a los archivos y crear una URL src para ellos.
var fname = 'myImage.jpg' zipObj.file(fname).async('blob').then((blob) => { var blobUrl = URL.createObjectURL(blob)
fuente