How to force download local information in the browser?

Asked

Viewed 1,423 times

3

I’m trying to do something kind of like this:

$('button').on('click', function() {

  obj = {};
   
  $('pseudoform').find('input,textarea').each(function() {
    obj[$(this).attr('name')] = String($(this).val());
  });

  json = JSON.stringify(obj);
  
  $('input[name=proof]').val(json);
  
  alert('Queria que baixasse: ' + json);

});
textarea,
input,
button {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<pseudoform>

  <label>Titulo:
    <input type="text" name="title" value="um valor">
  </label>

  <label>Descrição:
    <textarea name="desc">qualquer</textarea>
  </label>

  <input type="hidden" value="123456" name="challenge">
  <input type="hidden" value="999999" name="nonce">

</pseudoform>

<form target="#">

  <input type="hidden" value="{valor aqui}" name="proof">
  <button>Baixar</button>

</form>

The idea is that the value of proof is dynamically defined with a json. This json would have the values of all inputs that exist on top of it, within the pseudoform.

The other step would be for the user to download the content by clicking on the "download", this is the question.

How can I make Javascript, in the browser, force the user to download this content ({"title":"um valor","desc":"qualquer","challenge":"123456","nonce":"999999"}) when you click on "download"?


The reason for the user to download what he writes himself is that I need the user to subscribe to the content using Opengpg, with some smartcard. The server should only receive information from json (which is in input) and signature (Armored Detached Signature file) of this json.

2 answers

4

You can use a tag <a> with the attribute download so that you can force the json download you want by passing a blob like href along with the appropriate mime type. Follow an example below:

var btn  = document.getElementById('btnDownload');

	btn.addEventListener('click', function(){
		var obj  = {"id":1, "name": "Lorem"};  
	  	var data = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(obj));
		var a = document.getElementById('aDownload');
		a.setAttribute("href",data);
		a.setAttribute("download", "data.json");
		a.click();
	});
<a id="aDownload" style="display: none;"></a>
<button id="btnDownload">Baixar</button>

4


For reasons of compatibility, Internet Explorer use the navigator.msSaveBlob, another important point is to note that some browsers do not support the download attribute in some situations, such as cross-Domain, but I do not think influence the case, I just cited as informative.

Also occur the download attribute not be recognized, perhaps because it is an older browser or other behavior, in this case it would be interesting to use mime-type application/octet-stream which may help, an important detail of this is that on some mobile devices like browsers iOS the download will not occur in no way, then the solutions applied here are only supported in some cases.

An example would be something like:

function downloadData(name, data, nw) {

    //Internet Explorer
    if (navigator.msSaveBlob) {
        var blob = new Blob([data]); //Aplica o conteúdo para baixar
        navigator.msSaveBlob(blob, name); //Nome do arquivo
        return;
    }

    var body = document.body;

    var uridown = "data:application/octecstream," + encodeURIComponent(data);

    var el = document.createElement("a"); //Cria o link

    el.download = name; //Define o nome

    el.href = uridown; //Define a url

    //Adiciona uma classe css pra ocultar
    el.className = "hide-link";

    //Força abrir em uma nova janela
    if (nw) {
        el.target = "_blank";
    }

    //Adiciona no corpo da página (necessário para evitar comportamento variado em diferentes navegadores)
    body.appendChild(el);

    if (el.fireEvent) {
        //Simula o click pra navegadores com suporte ao fireEvent
        el.fireEvent("onclick");
    } else {
        //Simula o click com MouseEvents
        var evObj = document.createEvent("MouseEvents");
        evObj.initEvent("click", true, false);
        el.dispatchEvent(evObj);
    }

    //Remove o link da página
    setTimeout(function() {
        body.removeChild(el);
    }, 100);
}

In CSS add this (do not use display: none behavior may vary in different browsers):

.hide-link {
   position: absolute;
   top: -9999px;
   left: -9999px;
}

Use of script:

json = JSON.stringify(obj);

$('input[name=proof]').val(json);

downloadData('meujson.json', json);

To avoid Pagging I recommend that you prefer to try opening in a new page/tab, like this:

downloadData('meujson.json', json, true);

Example

Test the example:

downloadData("foo.json", '{ "foo": "bar" }', true);

function downloadData(name, data, nw) {

    //Internet Explorer
    if (navigator.msSaveBlob) {
        var blob = new Blob([data]); //Aplica o conteúdo para baixar
        navigator.msSaveBlob(blob, name); //Nome do arquivo
        return;
    }

    var body = document.body;

    var uridown = "data:application/octecstream," + encodeURIComponent(data);

    var el = document.createElement("a"); //Cria o link

    el.download = name; //Define o nome

    el.href = uridown; //Define a url

    //Adiciona uma classe css pra ocultar
    el.className = "hide-link";

    //Força abrir em uma nova janela
    if (nw) {
        el.target = "_blank";
    }

    //Adiciona no corpo da página (necessário para evitar comportamento variado em diferentes navegadores)
    body.appendChild(el);

    if (el.fireEvent) {
        //Simula o click pra navegadores com suporte ao fireEvent
        el.fireEvent("onclick");
    } else {
        //Simula o click com MouseEvents
        var evObj = document.createEvent("MouseEvents");
        evObj.initEvent("click", true, false);
        el.dispatchEvent(evObj);
    }

    //Remove o link da página
    setTimeout(function() {
        body.removeChild(el);
    }, 100);
}
.hide-link {
   position: absolute;
   top: -9999px;
   left: -9999px;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.