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?

Mikee
fonte
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)

Pekka
fonte
@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");
owencm
fonte
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");

Zibri
fonte
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);
Martino Dino
fonte
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.

Jesus MC
fonte
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.
Viacheslav Dobromyslov
fonte
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');
kevinarpe
fonte
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");
Chazt3n
fonte
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?)

Piskvor saiu do prédio
fonte