Descompactando arquivos

Eu quero exibir arquivos OpenOffice , .odt e .odp no lado do cliente usando um navegador da web.

Esses arquivos são arquivos compactados. Usando o Ajax, posso obter esses arquivos do servidor, mas esses são arquivos compactados. Eu tenho que descompactá-los usando JavaScript , eu tentei usar infate.js, http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt , mas sem sucesso.

Como posso fazer isso?

Eu escrevi um unzipper em Javascript. Funciona.

Ele se baseia no leitor de arquivos binários do Andy GP Na e na lógica de inflar RFC1951 da notmasteryet . Eu adicionei a class ZipFile.

exemplo de trabalho:
http://cheeso.members.winisp.net/Unzip-Example.htm (link inativo)

A fonte:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (link morto)

NB : os links estão mortos; Eu vou encontrar um novo hospedeiro em breve.

Incluído na fonte está uma página de demonstração ZipFile.htm e 3 scripts distintos, um para a class zipfile, um para a class inflar e um para uma class de leitura de arquivo binário. A demonstração também depende do jQuery e da jQuery UI. Se você acabou de baixar o arquivo js-zip.zip, toda a fonte necessária está lá.


Aqui está o que o código do aplicativo parece em 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("
"); 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" ), "
"); $("#"+id).html(content); $("#status").append("extract cb, entry(" + entryName + ") id(" + id + ")
"); $('#report').accordion('destroy'); $('#report').accordion({collapsible:true, active:false}); }); } // for each entry in the zip, extract it. for (var i=0; i\n
"; // contrive an id for the entry, make it unique var randomId = "id-"+ Math.floor((Math.random() * 1000000000)); entryInfo += "

Content:

\n"; // insert the info for one entry as the last child within the report div $("#report").append(entryInfo); // extract asynchronously entry.extract(extractCb(randomId)); } }

A demonstração funciona em alguns passos: O readFile fn é acionado por um clique e instancia um object ZipFile, que lê o arquivo zip. Há um retorno de chamada asynchronous para quando a leitura é concluída (geralmente acontece em menos de um segundo para zips de tamanho razoável) – nesta demonstração, o retorno de chamada é mantido na variável local doneReading, que simplesmente chama extractEntries , que descompacta cegamente todo o conteúdo do fornecido arquivo zip. Em um aplicativo real, você provavelmente escolheria algumas das inputs para extrair (permitir que o usuário selecione ou escolha uma ou mais inputs programaticamente, etc.).

O extractEntries fn itera todas as inputs e chama extract() em cada uma, passando um retorno de chamada. A descompression de uma input leva tempo, talvez 1s ou mais para cada input no arquivo zip, o que significa que a assincronia é apropriada. O retorno de chamada de extração simplesmente adiciona o conteúdo extraído a um acordeão jQuery na página. Se o conteúdo for binário, ele será formatado como tal (não mostrado).


Funciona, mas acho que o utilitário é um pouco limitado.

Por um lado: é muito lento. Leva ~ 4 segundos para descompactar o arquivo AppNote.txt de 140k do PKWare. O mesmo descompactar pode ser feito em menos de 0,5s em um programa .NET. EDIT : O Javascript ZipFile descompacta consideravelmente mais rápido do que isso agora, no IE9 e no Chrome. Ainda é mais lento que um programa compilado, mas é muito rápido para o uso normal do navegador.

Por outro: não faz streaming. Basicamente, ele absorve todo o conteúdo do arquivo zip na memory. Em um ambiente de programação “real”, você pode ler apenas os metadados de um arquivo zip (digamos, 64 bytes por input) e depois ler e descompactar os outros dados conforme desejado. Não há como fazer o pedido de veiculação como em JavaScript, pelo que sei, portanto, a única opção é ler o zip inteiro na memory e fazer access random a ele. Isso significa que colocará demandas irracionais na memory do sistema para grandes arquivos zip. Não é tanto um problema para um arquivo zip menor.

Além disso: Ele não lida com o arquivo zip “caso geral” – há muitas opções de zip que eu não me incomodei em implementar no unzipper – como criptografia ZIP, criptografia WinZip, zip64, nomes de arquivos codificados UTF-8 e assim em. ( EDIT – ele lida com nomes de arquivos codificados em UTF-8 agora). A class ZipFile lida com o básico, no entanto. Algumas dessas coisas não seriam difíceis de implementar. Eu tenho uma class de criptografia AES em JavaScript; que pode ser integrado para suportar criptografia. O suporte ao Zip64 provavelmente seria inútil para a maioria dos usuários de Javascript, já que ele é compatível com arquivos zip de 4gb – não é necessário extraí-los em um navegador.

Eu também não testei o caso para descompactar o conteúdo binário. No momento, ele descompacta o texto. Se você tiver um arquivo binário compactado, precisará editar a class ZipFile para manipulá-lo corretamente. Eu não descobri como fazer isso de forma limpa. Ele também faz arquivos binários agora.


EDIT – Atualizei a biblioteca de descompactação e demonstração do JS. Agora, ele faz arquivos binários, além do texto. Tornei-o mais resiliente e mais geral – agora você pode especificar a codificação a ser usada ao ler arquivos de texto. Além disso, a demonstração é expandida – mostra a descompactação de um arquivo XLSX no navegador, entre outras coisas.

Então, enquanto eu acho que é de utilidade e interesse limitados, funciona. Eu acho que funcionaria no Node.js.

Estou usando zip.js e parece ser bastante útil. Vale a pena dar uma olhada!

Confira a demonstração Unzip , por exemplo.

Eu achei jszip bastante útil. Eu usei até agora apenas para leitura, mas eles também criaram / editaram resources.

Código sábio parece algo como isto

 var new_zip = new JSZip(); new_zip.load(file); new_zip.files["doc.xml"].asText() // this give you the text in the file 

Uma coisa que eu notei é que parece que o arquivo tem que estar em formato de stream binário (leia usando o .readAsArrayBuffer de FileReader (), caso contrário eu estava recebendo erros dizendo que eu poderia ter um arquivo zip corrompido

Exemplo de código é dado no site do autor . Você pode usar babelfish para traduzir os textos (japonês para inglês).

Tanto quanto eu entendo japonês, este código zip inflate destina-se a decodificar os dados ZIP (streams) não arquivo ZIP.

Eu escrevi uma aula para isso também. http://blog.another-d-mention.ro/programming/read-load-files-from-zip-in-javascript/ Você pode carregar resources básicos como javascript / css / images diretamente do zip usando methods de class. Espero que ajude

Eu escrevi “Binary Tools for JavaScript”, um projeto de código aberto que inclui a capacidade de descompactar, unrar e untar: https://github.com/codedread/bitjs

Usado no meu leitor de quadrinhos: https://github.com/codedread/kthoom (também open source).

HTH!