Crie um arquivo na memory para o usuário baixar, não através do servidor

Existe alguma maneira eu posso criar um arquivo de texto no lado do cliente e solicitar ao usuário para baixá-lo, sem qualquer interação com o servidor? Eu sei que não posso escrever diretamente para a máquina deles (segurança e tudo), mas posso criar e solicitar que eles sejam salvos?

Você pode usar URIs de dados. O suporte do navegador varia; veja a Wikipedia . Exemplo:

text file 

O octeto-stream é forçar um prompt de download. Caso contrário, provavelmente será aberto no navegador.

Para CSV, você pode usar:

 CSV Octet 

Experimente a demonstração do jsFiddle .

Solução simples para navegadores prontos para HTML5 …

 function download(filename, text) { var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } 
 form * { display: block; margin: 10px; } 
 

Todo o exemplo acima funciona bem no Chrome e no IE, mas falha no Firefox. Por favor, considere append uma âncora ao corpo e removê-lo após o clique.

 var a = window.document.createElement('a'); a.href = window.URL.createObjectURL(new Blob(['Test,Text'], {type: 'text/csv'})); a.download = 'test.csv'; // Append anchor to body. document.body.appendChild(a); a.click(); // Remove anchor from body document.body.removeChild(a); 

Todas as soluções acima não funcionaram em todos os navegadores. Aqui está o que finalmente funciona no IE 10+, Firefox e Chrome (e sem jQuery ou qualquer outra biblioteca):

 save: function(filename, data) { var blob = new Blob([data], {type: 'text/csv'}); if(window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveBlob(blob, filename); } else{ var elem = window.document.createElement('a'); elem.href = window.URL.createObjectURL(blob); elem.download = filename; document.body.appendChild(elem); elem.click(); document.body.removeChild(elem); } } 

Observe que, dependendo da sua situação, você também pode querer chamar o URL.revokeObjectURL após remover o elem . De acordo com os documentos para URL.createObjectURL :

Cada vez que você chama createObjectURL (), um novo object URL é criado, mesmo que você já tenha criado um para o mesmo object. Cada um deles deve ser liberado chamando URL.revokeObjectURL () quando você não precisar mais deles. Os navegadores irão liberá-los automaticamente quando o documento for descarregado; no entanto, para desempenho ideal e uso de memory, se houver momentos seguros em que você possa descarregá-los explicitamente, deverá fazê-lo.

Estou feliz em usar o FileSaver.js . Sua compatibilidade é muito boa (IE10 + e tudo mais), e é muito simples de usar:

 var blob = new Blob(["some text"], { type: "text/plain;charset=utf-8;", }); saveAs(blob, "thing.txt"); 

O método a seguir funciona no IE11 +, no Firefox 25+ e no Chrome 30+:

 export  

Veja isto em Ação: http://jsfiddle.net/Kg7eA/

O Firefox e o Chrome suportam URI de dados para navegação, o que nos permite criar arquivos navegando para um URI de dados, enquanto o IE não o suporta para fins de segurança.

Por outro lado, o IE tem API para salvar um blob, que pode ser usado para criar e baixar arquivos.

Esta solução é extraída diretamente do repository github do tiddlywiki (tiddlywiki.com). Eu usei o tiddlywiki em quase todos os navegadores e funciona como um encanto:

 function(filename,text){ // Set up the link var link = document.createElement("a"); link.setAttribute("target","_blank"); if(Blob !== undefined) { var blob = new Blob([text], {type: "text/plain"}); link.setAttribute("href", URL.createObjectURL(blob)); } else { link.setAttribute("href","data:text/plain," + encodeURIComponent(text)); } link.setAttribute("download",filename); document.body.appendChild(link); link.click(); document.body.removeChild(link); } 

Repositório Github: Download saver module

Se você quiser apenas converter uma string para estar disponível para download, você pode tentar usar o jQuery.

 $('a.download').attr('href', 'data:application/csv;charset=utf-8,' + encodeURI(data)); 

Solução que funciona no IE10: (Eu precisava de um arquivo csv, mas é o suficiente para alterar o tipo e nome do arquivo para txt)

 var csvContent=data; //here we load our csv data var blob = new Blob([csvContent],{ type: "text/csv;charset=utf-8;" }); navigator.msSaveBlob(blob, "filename.csv") 
 var element = document.createElement('a'); element.setAttribute('href', 'data:text/text;charset=utf-8,' + encodeURI(data)); element.setAttribute('download', "fileName.txt"); element.click(); 

A partir de abril de 2014, as APIs do FileSytem não podem ser padronizadas no W3C. Qualquer um que olhe para a solução com o blob deve colocar o assunto com cuidado, eu acho.

HTML5 balança as cabeças

Lista de discussão W3C na API FileSytem

Com base na resposta @Rick que foi realmente útil.

Você precisa escaping dos data da string se quiser compartilhá-lo desta maneira:

 $('a.download').attr('href', 'data:application/csv;charset=utf-8,'+ encodeURI(data)); 

`Desculpe eu não posso comentar sobre @ resposta do Rick, devido à minha baixa reputação atual no StackOverflow.

Uma sugestão de edição foi compartilhada e rejeitada.

Como mencionado anteriormente, o filesaver é um ótimo pacote para trabalhar com arquivos no lado do cliente. Mas, não faz bem com arquivos grandes. O StreamSaver.js é uma solução alternativa (que é apontada no FileServer.js) que pode manipular arquivos grandes:

 const fileStream = streamSaver.createWriteStream('filename.txt', size); const writer = fileStream.getWriter(); for(var i = 0; i < 100; i++){ var uint8array = new TextEncoder("utf-8").encode("Plain Text"); writer.write(uint8array); } writer.close() 

Você pode até mesmo fazer um melhor que apenas o URI – usando o Google Chrome, você também pode sugerir o nome do arquivo, conforme explicado nesta postagem do blog sobre como nomear um download ao usar URIs .

Se o arquivo contiver dados de texto, uma técnica que uso é colocar o texto em um elemento textarea e fazer com que o usuário o selecione (clique em textarea then ctrl-A) e depois copie seguido por um colar em um editor de texto.

Na verdade, é possível – use o Flash.

Você pode gerar o conteúdo com JS e, em seguida, inicializar alguns flash vars ou apenas fazer tudo dentro de um filme flash.

Por favor, dê uma olhada nisso para algumas observações importantes.