javascript - with - title attribute html




JavaScript: crie e salve o arquivo (8)

Tenho dados que desejo gravar em um arquivo e abro um diálogo de arquivo para o usuário escolher onde salvar o arquivo. Seria ótimo se funcionasse em todos os navegadores, mas funcionasse no Chrome. Eu quero fazer isso tudo do lado do cliente.

Basicamente eu quero saber o que colocar nessa função:

saveFile: function(data)
{
}

Quando a função recebe dados, o usuário seleciona um local para salvar o arquivo e cria um arquivo nesse local com esses dados.

Usar HTML também é bom, se isso ajudar.


Escolher o local para salvar o arquivo antes de criá-lo não é possível. Mas é possível, pelo menos no Chrome, gerar arquivos usando apenas JavaScript. Aqui está um exemplo antigo de criação de um arquivo CSV. O usuário será solicitado a fazer o download. Isso, infelizmente, não funciona bem em outros navegadores, especialmente no IE.

<!DOCTYPE html>
<html>
<head>
    <title>JS CSV</title>
</head>
<body>
    <button id="b">export to CSV</button>
    <script type="text/javascript">
        function exportToCsv() {
            var myCsv = "Col1,Col2,Col3\nval1,val2,val3";

            window.open('data:text/csv;charset=utf-8,' + escape(myCsv));
        }

        var button = document.getElementById('b');
        button.addEventListener('click', exportToCsv);
    </script>
</body>
</html>


Para o Chrome e o Firefox, tenho usado um método puramente JavaScript.

(Meu aplicativo não pode fazer uso de um pacote como o Blob.js porque ele é servido por um mecanismo especial: um DSP com um servidor WWWeb abarrotado e pouco espaço para qualquer coisa.)

function FileSave(sourceText, fileIdentity) {
    var workElement = document.createElement("a");
    if ('download' in workElement) {
        workElement.href = "data:" + 'text/plain' + "charset=utf-8," + escape(sourceText);
        workElement.setAttribute("download", fileIdentity);
        document.body.appendChild(workElement);
        var eventMouse = document.createEvent("MouseEvents");
        eventMouse.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        workElement.dispatchEvent(eventMouse);
        document.body.removeChild(workElement);
    } else throw 'File saving not supported for this browser';
}

Notas, advertências e palavras-doninha:

  • Eu obtive sucesso com esse código nos clientes Chrome e Firefox executados nos ambientes Linux (Maipo) e Windows (7 e 10).
  • No entanto, se sourceText for maior que um MB, o Chrome às vezes (apenas às vezes) fica preso em seu próprio download sem qualquer indicação de falha; O Firefox, até agora, não exibiu esse comportamento. A causa pode ser alguma limitação de bolha no Chrome. Francamente, eu simplesmente não sei; Se alguém tiver alguma idéia de como corrigir (ou pelo menos detectar), por favor poste. Se a anomalia do download ocorrer, quando o navegador Chrome for fechado, ele gerará um diagnóstico como
  • Este código não é compatível com o Edge ou o Internet Explorer; Eu não tentei Opera ou Safari.

Para o navegador mais recente, como o Chrome, você pode usar a API de arquivos, como neste tutorial :

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.PERSISTENT, 5*1024*1024 /*5MB*/, saveFile, errorHandler);

Tentei isso no console, e funciona.

var aFileParts = ['<a id="a"><b id="b">hey!</b></a>'];
var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // the blob
window.open(URL.createObjectURL(oMyBlob));

Uma melhoria muito pequena do código por Awesomeness01 (sem necessidade de tag âncora) com adição como sugerido por trueimage (suporte para IE):

// Function to download data to a file
function download(data, filename, type) {
    var file = new Blob([data], {type: type});
    if (window.navigator.msSaveOrOpenBlob) // IE10+
        window.navigator.msSaveOrOpenBlob(file, filename);
    else { // Others
        var a = document.createElement("a"),
                url = URL.createObjectURL(file);
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(function() {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);  
        }, 0); 
    }
}

Testado para funcionar corretamente no Chrome, no FireFox e no IE10.

No Safari, os dados são abertos em uma nova guia e é necessário salvar manualmente esse arquivo.


setTimeout("create('Hello world!', 'myfile.txt', 'text/plain')");
function create(text, name, type) {
  var dlbtn = document.getElementById("dlbtn");
  var file = new Blob([text], {type: type});
  dlbtn.href = URL.createObjectURL(file);
  dlbtn.download = name;
}
<a href="javascript:void(0)" id="dlbtn"><button>click here to download your file</button></a>


function download(text, name, type) {
  var a = document.getElementById("a");
  var file = new Blob([text], {type: type});
  a.href = URL.createObjectURL(file);
  a.download = name;
}
<a href="" id="a">click here to download your file</a>
<button onclick="download('file text', 'myfilename.txt', 'text/plain')">Create file</button>

E você faria o download do arquivo colocando o atributo de download na tag de âncora.

A razão pela qual eu gosto disso melhor do que criar um URL de dados é que você não precisa fazer um URL longo e grande, basta gerar um URL temporário.





save