Compactar arquivos com JavaScript
Veja como compactar artigos utilizando JavaScript
Neste artigo vamos ver como podemos compactar arquivos utilizando o JavaScript. Para fazer isso, vamos usar duas bibliotecas, uma chamada JSZIP e outra chamada JZIP-UTILS. Você pode fazer o download e ver a documentação neste link:
https://github.com/Stuk/jszip-utils/tree/master/dist
Para fazer a instalação do JsZip, depois de baixar os arquivos do site é necessário incluir em seu projeto o arquivo dist/jszip.js ou o dist/jszip.min.js, que é o mesmo arquivo, porem minificado.
Para instalar o JsZip-Utils, será necessário baixar o arquivo jszip-utils.js ou o arquivo jszip-utils.min.js do segundo link informado neste artigo.
Vamos ver dois exemplos, o primeiro seria como compactar 1 arquivo, o segundo como compactar vários arquivos. Os exemplos a seguir foram feitos pelo navegador, inserindo o código JavaScript numa página HTML.
Importante: Para o teste destes arquivos, você deve fazer a partir de um servidor web, abrir direto o script no navegador não vai funcionar.
Compactar arquivo
O primeiro que precisamos fazer é adicionar os dois arquivos que fizemos download, o JsZip e o JsZip-Utils. Você pode usar tanto a versão normal quanto a minificada
<script type="text/javascript" src="jszip.min.js"></script>
<script type="text/javascript" src="jszip-utils.min.js"></script>
Na sequência vamos utilizar o JSZipUtils para extrair o conteúdo do arquivo que vamos compactar. No exemplo a seguir, estamos abrindo um arquivo chamado "relatorio.pdf" que está localizado no mesmo local onde está sendo executado o nosso script.
JSZipUtils.getBinaryContent("relatorio.pdf", function (err, data) {
if(err) {
throw err; // or handle the error
}
console.log(data);
})
Com os dados do arquivo em mãos, podemos criar o nosso arquivo compactado.
JSZipUtils.getBinaryContent("relatorio.pdf", function (err, data) {
if(err) {
throw err; // or handle the error
}
var zip = new JSZip();
zip.file("relatorio.pdf", data, {binary:true});
})
Para criar uma nova instância do JsZip fizemos assim:
var zip = new JSZip();
E para adicionar o arquivo:
zip.file("relatorio.pdf", data, {binary:true});
O método file recebeu como parâmetro o nome do arquivo, o seu conteúdo e um parâmetro informando que o conteúdo é no formato binário.
Nossa instância do JSZip recebeu o nosso arquivo, agora chegou a hora de fechar o arquivo e forçar o download. Para isso utilizamos o método generateAsync.
zip.generateAsync({type:"blob"}).then(function(content) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(content);
a.href = url;
a.download = "arquivo_compactado.zip";
a.click();
window.URL.revokeObjectURL(url);
});
O método generateAsync faz a leitura do conteúdo do nosso zip e permite manipular este conteudo para salvar. Para forçar o download, precisamos criar um elemento "a" em nosso DOM, adicionar o conteudo do zip e simular um click, desta forma ele faz o download do conteúdo.
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(content);
a.href = url;
a.download = "arquivo_compactado.zip";
a.click();
window.URL.revokeObjectURL(url);
A variável "a" tem um elemento HTML "a" que é usado para criar links. Este elemento é adicionado ao DOM utilizando document.body.appendChild.
Nosso elemento A teve as seguintes propriedades definidas:
- Style: Usado para deixar ele oculto
- Url: Adiciona o link para o conteúdo do zip, utilizando window.URL.createObjectURL. Este método recebe como parâmetro um objeto File, Blob, ou MediaSource.
- Download: Recebe o nome do arquivo zip que estamos criando.
No final utilizamos o método click para simular o clique neste elemento oculto e fazer o download. O método window.URL.revokeObjectURL da última linha elimina a URL que criamos com o método createObjectURL.
O nosso código completo fica da seguinte forma:
<script type="text/javascript" src="jszip.min.js"></script>
<script type="text/javascript" src="jszip-utils.min.js"></script>
<script type="text/javascript">
JSZipUtils.getBinaryContent("relatorio.pdf", function (err, data) {
if(err) {
throw err;
}
var zip = new JSZip();
zip.file("relatorio.pdf", data, {binary:true});
zip.generateAsync({type:"blob"}).then(function(content) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(content);
a.href = url;
a.download = "arquivo_compactado.zip";
a.click();
window.URL.revokeObjectURL(url);
});
})
</script>
Compactar vários arquivos
Para compactar vários arquivos será necessário adaptar este código inicial e fazer duas melhorias, a primeira será criar um array com os arquivos que serão compactados.
const arquivos = ["1976/BEE-s.jpg", "1976/BEF-s.jpg"];
A segunda coisa a fazer é encapsular a lógica usada para extrair o conteúdo de um arquivo. No exemplo anterior usados a biblioteca JSZipUtils e o método getBinaryContent. Vamos criar uma função auxiliar e colocar este código dentro de uma Promisse. Promisses são objetos usados para realizar processamentos assíncronos.
function ArquivosPromise(arquivo) {
return new Promise(function(resolve, reject) {
JSZipUtils.getBinaryContent(arquivo, function (err, data) {
if(err) {
reject(err);
} else {
resolve(data);
}
});
});
}
Para criar um arquivo compactado com vários arquivos vamos iterar o nosso array de arquivos e utilizar esta função auxiliar chamada ArquivosPromise para adicionar cada arquivo dentro de nosso zip.
O código com a solução completa fica assim:
let zip = new JSZip();
//zip.folder("1976");
const arquivos = ["1976/BEE-s.jpg", "1976/BEF-s.jpg"];
for (let arquivo of arquivos) {
zip.file(arquivo, ArquivosPromise(arquivo), {binary:true});
};
zip.generateAsync({type:"blob"}).then(function(content) {
console.log(content);
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(content);
a.href = url;
a.download = "pasta_compactada.zip";
a.click();
window.URL.revokeObjectURL(url);
});