Podemos usar a URL api, em particular URL.createObjectURL () , eo Blob API para codificar e baixar praticamente qualquer coisa.
Se o seu download for pequeno, isso funcionará bem:
document.body.innerHTML +=
`<a id="download" download="PATTERN.json" href="${URL.createObjectURL(new Blob([JSON.stringify("HELLO WORLD", null, 2)]))}"> Click me</a>`
download.click()
download.outerHTML = ""
Se o seu download for grande, em vez de usar o DOM, a melhor maneira é criar um elemento de link com os parâmetros de download e acionar um clique.
Observe que o elemento link não está anexado ao documento, mas o clique funciona mesmo assim! É possível criar um download de muitas centenas de Mo dessa maneira.
const stack = {
some: "stuffs",
alot: "of them!"
}
BUTTONDOWNLOAD.onclick = (function(){
let j = document.createElement("a")
j.id = "download"
j.download = "stack_"+Date.now()+".json"
j.href = URL.createObjectURL(new Blob([JSON.stringify(stack, null, 2)]))
j.click()
})
<button id="BUTTONDOWNLOAD">DOWNLOAD!</button>
Bônus!Faça o download de qualquer objeto cíclico , evite os erros:
TypeError: valor do objeto cíclico (Firefox) TypeError: Convertendo
estrutura circular para JSON (Chrome e Opera) TypeError: Circular
referência no argumento do valor não suportada (Edge)
Usando https://github.com/douglascrockford/JSON-js/blob/master/cycle.js
Neste exemplo, baixando o document
objeto como json.
/* JSON.decycle */
if(typeof JSON.decycle!=="function"){JSON.decycle=function decycle(object,replacer){"use strict";var objects=new WeakMap();return(function derez(value,path){var old_path;var nu;if(replacer!==undefined){value=replacer(value)}
if(typeof value==="object"&&value!==null&&!(value instanceof Boolean)&&!(value instanceof Date)&&!(value instanceof Number)&&!(value instanceof RegExp)&&!(value instanceof String)){old_path=objects.get(value);if(old_path!==undefined){return{$ref:old_path}}
objects.set(value,path);if(Array.isArray(value)){nu=[];value.forEach(function(element,i){nu[i]=derez(element,path+"["+i+"]")})}else{nu={};Object.keys(value).forEach(function(name){nu[name]=derez(value[name],path+"["+JSON.stringify(name)+"]")})}
return nu}
return value}(object,"$"))}}
document.body.innerHTML +=
`<a id="download" download="PATTERN.json" href="${URL.createObjectURL(new Blob([JSON.stringify(JSON.decycle(document), null, 2)]))}"></a>`
download.click()