Baixar arquivo de URL de dados


126

Estou brincando com a idéia de criar um utilitário zip / descompactar completamente baseado em JavaScript que qualquer pessoa possa acessar de um navegador. Eles podem simplesmente arrastar o zip diretamente para o navegador e isso permitirá que eles baixem todos os arquivos. Eles também podem criar novos arquivos zip arrastando arquivos individuais para dentro.

Eu sei que seria melhor fazê-lo no servidor, mas este projeto é apenas um pouco divertido.

Arrastar arquivos para o navegador deve ser fácil se eu tirar proveito dos vários métodos disponíveis. (Estilo Gmail)

Espero que a codificação / decodificação esteja correta. Eu vi algumas bibliotecas as3 zip, então eu tenho certeza que devo ficar bem com isso.

Meu problema está baixando os arquivos no final.

window.location = 'data:jpg/image;base64,/9j/4AAQSkZJR....' 

isso funciona bem no firefox, mas não no chrome.

Posso incorporar os arquivos como imagens no Chrome <img src="data:jpg/image;ba.." />, mas os arquivos não serão necessariamente imagens. Eles podem ter qualquer formato.

Alguém pode pensar em outra solução ou algum tipo de solução alternativa?


Infelizmente, o suporte atual é limitado
— Casebash ''

Respostas:


42

Ideias:

  • Experimente um <a href="data:...." target="_blank">(não testado)

  • Use downloadify em vez de URLs de dados (funcionaria também para o IE)


@jcubic obrigado por apontar o link morto. O novo local de download parece ser github.com/dcneiner/Downloadify
— Pekka

Se você não pode usar o Flash, mas está executando um componente Java do lado do servidor, pode usar o seguinte: github.com/suprememoocow/databounce . Ele usa um Servlet para 'devolver' os dados do cliente. Seria bastante fácil de realizar o mesmo truque em outras tecnologias do lado do servidor, como Python, ASP.NET etc
— Andrew Newdigate

Existe uma maneira de fazer isso sem flash? URL de dados para todos os navegadores, exceto o IE e algum tipo de ActiveX foo para o IE? (Dessa forma eu consegui tocar música sem flash: áudio HTML5 para todos os navegadores mas IE e ActiveX para o IE.)
— panzi

O Downloadify espera o flash player no navegador. Se o usuário não tiver um flash player, o arquivo não será baixado.
— Jeevanandan J

186

Se você também quiser dar um nome sugerido ao arquivo (em vez do 'download' padrão), use o seguinte no Chrome, Firefox e em algumas versões do IE:

function downloadURI(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  delete link;
}

E o exemplo a seguir mostra seu uso:

downloadURI("data:text/html,HelloWorld!", "helloWorld.txt");

6
Você pode simplificar isso com link.click()em vez de seu eventFire-função ... jsfiddle.net/ARTsinn/Ezx5m
— yckart

3
Ótima solução. mas o que o link se torna depois?
— Webshaker

6
A variável 'link' fica fora do escopo no final da função (observe que nunca a adicionamos ao dom), portanto será coletada como lixo logo após.
— owencm

8
Isso funciona apenas no Chrome. Se você deseja que ele funcione no Firefox / IE, consulte a resposta do @MartinoDino.
— TrueWill 17/07/2015

1
Eu tentei com o download.js , conforme sugerido aqui e parece funcionar. :)
— joaorodr84

53

function download(dataurl, filename) {
  var a = document.createElement("a");
  a.href = dataurl;
  a.setAttribute("download", filename);
  a.click();
}

download("data:text/html,HelloWorld!", "helloWorld.txt");

ou:

function download(url, filename) {
fetch(url).then(function(t) {
    return t.blob().then((b)=>{
        var a = document.createElement("a");
        a.href = URL.createObjectURL(b);
        a.setAttribute("download", filename);
        a.click();
    }
    );
});
}

download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");


evento click no elemento inexistente: D não há necessidade de appendchild.
— Zibri

1
sim. você pode simplesmente chamar a.click () depois de criar o elemento 'a' e definir o href de a.
— user1709076

no passado, chamar a.click () diretamente não funcionava, mas funcionava com o evento. Agora os dois trabalham.
— Zibri

1
Isso funciona na maioria dos navegadores modernos, mas eu observaria que é necessário anexar ao documento e removê-lo para dar suporte a alguns navegadores mais antigos.
— 22419 owencm

3
Sua segunda solução deve ser usada sempre que o dataUri ficar muito grande (depende do navegador, mas o Chrome não aceita Uri de vários megabytes na minha experiência). Consulte também stackoverflow.com/questions/38781968/… .
— Neural5torm 31/07/19

27

Deseja compartilhar minha experiência e ajudar alguém preso aos downloads que não estão funcionando no Firefox e resposta atualizada para 2014. O snippet abaixo funcionará no firefox e no chrome e aceitará um nome de arquivo:

  // Construct the <a> element
  var link = document.createElement("a");
  link.download = thefilename;
  // Construct the uri
  var uri = 'data:text/csv;charset=utf-8;base64,' + someb64data
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  // Cleanup the DOM
  document.body.removeChild(link);

4
Infelizmente, não funciona no Safari. O Safari parece não reconhecer o downloadatributo. De qualquer forma, obrigado, isso é o mais próximo que posso chegar no momento.
— Moritz Petersen

isso está fazendo com que a janela seja redirecionada para o valor href para mim no IE 11. prevetDefault (); não parar o comportamento no IE
— b_dubb

1
Graças, também, se btoanão for definida (por exemplo, no nó eslinted projecto interface) const btxt = new Buffer(text).toString('base64'); const uri = 'data:text/csv;charset=utf-8;base64,' + btxt + ';'
— Ivan Borshchov

2
excluir o link não faz sentido, fica fora do escopo na próxima linha e será coletado como lixo, não é um destino válido para exclusão.
— precisa saber é o seguinte

1
não há necessidade de document.body.appendChild ... ver a minha resposta stackoverflow.com/a/45905238/236062
— Zibri

13

Aqui está uma solução JavaScript pura que testei trabalhando no Firefox e Chrome, mas não no Internet Explorer:

function downloadDataUrlFromJavascript(filename, dataUrl) {

    // Construct the 'a' element
    var link = document.createElement("a");
    link.download = filename;
    link.target = "_blank";

    // Construct the URI
    link.href = dataUrl;
    document.body.appendChild(link);
    link.click();

    // Cleanup the DOM
    document.body.removeChild(link);
    delete link;
}

Soluções entre navegadores encontradas até agora:

downloadify -> Requer Flash

databounce -> Testado no IE 10 e 11 e não funciona para mim. Requer um servlet e alguma personalização. (Detecta incorretamente o navegador. Eu tive que configurar o IE no modo de compatibilidade para testar, charset padrão no servlet, objeto de opções JavaScript com o caminho correto do servlet para caminhos absolutos ...) Para navegadores que não sejam do IE, ele abre o arquivo na mesma janela.

download.js -> http://danml.com/download.html Outra biblioteca semelhante, mas não testada. Alega ser JavaScript puro, não requer servlet nem Flash, mas não funciona no IE <= 9.


download.js é muito bom. Acabei de fazer uma verificação rápida no IE11, funciona. Muito obrigado!
— Ricky Jiao

12

Existem várias soluções, mas elas dependem do HTML5 e ainda não foram implementadas completamente em alguns navegadores. Os exemplos abaixo foram testados no Chrome e Firefox (parcialmente funciona).

  1. Exemplo de tela com suporte para salvar no arquivo. Basta definir seu document.location.hrefURI de dados.
  2. Exemplo de download de âncora . Ele usa <a href="your-data-uri" download="filename.txt">para especificar o nome do arquivo.

3
exemplo de canvas leva a 404
— Karel Bílek

O atributo de download está funcionando para mim, para um URL de dados em PDF no Chrome e no Safari para dispositivos móveis.
— bbsimonbb

7

Combinando respostas do @owencm e do @ Chazt3n, essa função permitirá o download de texto do IE11, Firefox e Chrome. (Desculpe, não tenho acesso ao Safari ou Opera, mas por favor, adicione um comentário se você tentar e funcionar.)

initiate_user_download = function(file_name, mime_type, text) {
    // Anything but IE works here
    if (undefined === window.navigator.msSaveOrOpenBlob) {
        var e = document.createElement('a');
        var href = 'data:' + mime_type + ';charset=utf-8,' + encodeURIComponent(text);
        e.setAttribute('href', href);
        e.setAttribute('download', file_name);
        document.body.appendChild(e);
        e.click();
        document.body.removeChild(e);
    }
    // IE-specific code
    else {
        var charCodeArr = new Array(text.length);
        for (var i = 0; i < text.length; ++i) {
            var charCode = text.charCodeAt(i);
            charCodeArr[i] = charCode;
        }
        var blob = new Blob([new Uint8Array(charCodeArr)], {type: mime_type});
        window.navigator.msSaveOrOpenBlob(blob, file_name);
    }
}

// Example:
initiate_user_download('data.csv', 'text/csv', 'Sample,Data,Here\n1,2,3\n');

1

Para qualquer pessoa com problemas no IE:

Voto a favor da resposta aqui de Yetti: salvando a tela localmente no IE

dataURItoBlob = function(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/png'});
}

var blob = dataURItoBlob(uri);
window.navigator.msSaveOrOpenBlob(blob, "my-image.png");

0

Seu problema basicamente se resume a "nem todos os navegadores suportam isso".

Você pode tentar uma solução alternativa e veicular os arquivos descompactados de um objeto Flash, mas perderá a pureza somente de JS (de qualquer forma, não tenho certeza se atualmente você pode "arrastar arquivos para o navegador" sem algum tipo de solução alternativa do Flash. - esse recurso talvez seja um HTML5?)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.