Vamos resolver um problema não trivial. Imagine que você precise baixar os dados pela interface de forma elementar, por exemplo, clicar no botão "Baixar arquivos".
Vamos pegar o Chrome v.88 padrão. A tarefa soa assim:
- Gere arquivos do lado do cliente.
- Baixe todos os arquivos gerados com um clique.
Pode ser qualquer coisa: um monte de binários, grandes arquivos com backups, uma galeria de fotos e assim por diante. Falaremos especificamente sobre o mecanismo de download como tal, por isso tomaremos o download de texto e imagens como exemplo.
Claro, você pode resolver esse problema simplesmente compactando todos os arquivos necessários em um arquivo ZIP e, em seguida, baixando-o. Acontece que o usuário baixa um único arquivo, que ele então descompacta sozinho. Por exemplo, você pode usar a biblioteca jszip , que permite baixar um conjunto de arquivos compactando-os.
Aqui está um pequeno exemplo de download pré-compactado dos documentos:
var zip = new JSZip();
zip.file("Hello.txt", "Hello World\n");
var img = zip.folder("images");
img.file("smile.gif", imgData, {base64: true}); zip.generateAsync({type:"blob"}).then(function(content) {
// see FileSaver.js
saveAs(content, "example.zip"); });
"Onde está a não trivialidade aqui?" - você pergunta. E você estará certo. E se estamos falando de download simultâneo de dois, três ou dez arquivos do site? Por exemplo: existe uma lista no select, onde você pode selecionar um determinado número de arquivos para baixar. Vamos introduzir uma condição adicional: o usuário não possui um arquivador instalado, então descartamos a opção de compactação para o arquivo. Como resolver este problema?
Primeiro, vamos preparar o navegador. O Chrome proíbe o download de vários arquivos por padrão. Isto é por razões de segurança. Portanto, esta função deve primeiro ser desbloqueada nas configurações do navegador:
- Vamos para as configurações do site: chrome: // settings / content.
- Vá para Permissões adicionais.
- Escolha downloads automáticos.
- Adicione o site necessário à categoria Permitir.
Ótimo, agora seu navegador se
Abordagem nº 1 - FileReader
Vejamos a primeira abordagem usando o exemplo de geração de arquivos usando FileReader e a API de leitura base64. Noto imediatamente que FileReader tem uma API bastante extensa, então escolha o que você mais gosta: text, arrayBuffer ou binaryString.
(function () {
const button = document.getElementById("download_with_reader");
const content = ["content-1", "content-2", "content-3"];
const createLink = () => {
let link = document.createElement('a');
link.download = 'hello.txt';
return link;
}
const generateBlob = () => {
for (const [index, value] of content.entries()) {
const blob = new Blob([value], { type: "text/plain" });
download(blob, index);
}
}
const download = (blob, index) => {
const link = createLink();
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function () {
link.href = reader.result;
link.download = `content-${index+1}.txt`;
link.click();
}
}
button.addEventListener("click", generateBlob);
}) ();
[código no Gitlab]
Abordagem # 2 - createObjectURL
Você também pode usar createObjectURL - permite armazenar objetos File ou Blobs.
(function () {
const button = document.getElementById("download_with_url_object");
const content = ["content-1", "content-2", "content-3"];
const createLink = () => {
let link = document.createElement('a');
link.download = 'hello.txt';
return link;
}
const generateBlob = () => {
for (const [index, value] of content.entries()) {
const blob = new Blob([value], { type: "text/plain" });
download(blob, index);
}
}
const download = (blob, index) => {
const link = createLink();
link.href = URL.createObjectURL(blob);
link.download = `content-${index+1}.txt`;
link.click();
URL.revokeObjectURL(link.href);
}
button.addEventListener("click", generateBlob);
}) ();
[código no Gitlab]
Abordagem nº 3 - Baixar do URL
As duas opções acima geram arquivos do lado do cliente. Claro, nem sempre será o caso, de vez em quando recebemos arquivos do back-end por meio de links diretos. Isso pode ser feito baixando de um URL. O Chrome requer latência, portanto, a implementação de latência artificial se tornará um recurso desse método.
(function () {
(function () {
const button = document.getElementById("download_with_request");
const urls = ["images/image-1.jpg", "images/image-2.jpg", "images/image-3.jpg"];
const delay = () => new Promise(resolve => setTimeout(resolve, 1000));
const downloadWithRequest = async () => {
for await (const [index, url] of urls.entries()) {
await delay();
const link = document.createElement("a");
link.href = url;
link.download = `image-${index+1}`;
link.click();
}
}
button.addEventListener("click", downloadWithRequest);
}) ();
[código no Gitlab]
Total
Aqui estão três maneiras bastante simples de baixar vários arquivos de um site ao mesmo tempo e fazer isso rapidamente. O principal é ativar as permissões necessárias para um site específico e, em seguida, escolher o método de sua preferência.