Laden Sie das JSON-Objekt als Datei aus dem Browser herunter

143

Ich habe den folgenden Code, mit dem Benutzer Datenzeichenfolgen in einer CSV-Datei herunterladen können.

exportData = 'data:text/csv;charset=utf-8,';
exportData += 'some csv strings';
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);

Es funktioniert einwandfrei, wenn der Client den Code ausführt, eine leere Seite generiert und die Daten in die CSV-Datei herunterlädt.

Also habe ich versucht, dies mit JSON-Objekt wie zu tun

exportData = 'data:text/json;charset=utf-8,';
exportData += escape(JSON.stringify(jsonObject));
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);

Ich sehe jedoch nur eine Seite mit den darauf angezeigten JSON-Daten, ohne sie herunterzuladen.

Ich habe einige Nachforschungen angestellt und diese behauptet zu funktionieren, aber ich sehe keinen Unterschied zu meinem Code.

Vermisse ich etwas in meinem Code?

Danke, dass du meine Frage gelesen hast :)

Eugene Yu
quelle

Antworten:

255

So habe ich es für meine Bewerbung gelöst:

HTML: <a id="downloadAnchorElem" style="display:none"></a>

JS (reines JS, hier nicht jQuery):

var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(storageObj));
var dlAnchorElem = document.getElementById('downloadAnchorElem');
dlAnchorElem.setAttribute("href",     dataStr     );
dlAnchorElem.setAttribute("download", "scene.json");
dlAnchorElem.click();

In diesem Fall storageObjhandelt es sich um das js-Objekt, das Sie speichern möchten, und "scene.json" ist nur ein Beispielname für die resultierende Datei.

Dieser Ansatz hat die folgenden Vorteile gegenüber anderen vorgeschlagenen:

  • Es muss kein HTML-Element angeklickt werden
  • Das Ergebnis wird so benannt, wie Sie es möchten
  • Keine jQuery erforderlich

Ich brauchte dieses Verhalten ohne explizites Klicken, da ich den Download irgendwann automatisch von js auslösen möchte.

JS-Lösung (kein HTML erforderlich):

  function downloadObjectAsJson(exportObj, exportName){
    var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
    var downloadAnchorNode = document.createElement('a');
    downloadAnchorNode.setAttribute("href",     dataStr);
    downloadAnchorNode.setAttribute("download", exportName + ".json");
    document.body.appendChild(downloadAnchorNode); // required for firefox
    downloadAnchorNode.click();
    downloadAnchorNode.remove();
  }
Volzotan
quelle
3
Dies ist die einzige Lösung, die für mehr als = ~ 2000 Zeichen Daten funktioniert. Weil Sie Daten vorangestellt haben:
rjurney
1
Kann mich jemand auf eine Spezifikation oder MDN-Seite verweisen, die detaillierter erklärt, wie diese ganze vorangestellte Datentyp-Sache funktioniert, dh. "data: text / json; charset = utf-8"? Ich benutze dies, aber es fühlt sich wie Magie an, wäre toll, die Details zu lesen, aber ich weiß nicht einmal, wie ich danach googeln soll.
Sidewinderguy
1
Dies funktioniert jedoch nicht im Internet Explorer, wenn Sie eine große Datei mit mehr als 2000 Zeichen herunterladen müssen.
user388969
12
Dies wird jedoch nicht ohne Grenzen funktionieren. Sie können nur etwa 1 MB Daten herunterladen. Zum Beispiel var storageObj = []; for (var i=0; i<1000000; ++i) storageObj.push('aaa');gibt "Download fehlgeschlagen - Netzwerkfehler" in Chrome 61
oseiskar
1
@YASHDAVE JSON.stringify(exportObj, null, 2)stattdessen verwenden
TryingToImprove
40

Ich habe eine Antwort gefunden.

var obj = {a: 123, b: "4 5 6"};
var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(obj));

$('<a href="data:' + data + '" download="data.json">download JSON</a>').appendTo('#container');

scheint für mich gut zu funktionieren.

** Alle Gutschriften gehen an @ cowboy-ben-alman, der der Autor des obigen Codes ist **

Eugene Yu
quelle
@Cybear kannst du mir die dritte Zeile erklären?
Rahul Khatri
Sie sollten Daten voranstellen: Ihrer URL, andernfalls erreicht der Benutzer in vielen Browsern wahrscheinlich ein Limit von 2000 Zeichen.
rjurney
Hey, ich weiß, dass es eine alte Antwort ist, aber ich weiß, dass diese Lösung nicht im IE funktioniert (alle). Der IE ist nicht mit der Download-Attributreferenz vertraut - Link
Ayalon Grinfeld
25

Dies wäre eine reine JS-Version (angepasst von Cowboys):

var obj = {a: 123, b: "4 5 6"};
var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(obj));

var a = document.createElement('a');
a.href = 'data:' + data;
a.download = 'data.json';
a.innerHTML = 'download JSON';

var container = document.getElementById('container');
container.appendChild(a);

http://jsfiddle.net/sz76c083/1

jbcdefg
quelle
3
Vielen Dank für die Antwort, auch nachdem es 2 Jahre her ist, seit ich diese Frage gestellt habe! Ich bevorzuge reines JS gegenüber jQuery-Syntax.
Eugene Yu
Sie sollten Daten voranstellen: Ihrer URL, andernfalls erreicht der Benutzer in vielen Browsern wahrscheinlich ein Limit von 2000 Zeichen.
rjurney
Wie kann ich diesen Download beim Laden der Seite starten lassen? Wenn ein Benutzer die Seiten-URL durchsucht, wird er zum Herunterladen
aufgefordert
1
Der heutige Test in Edge: data.json konnte nicht heruntergeladen werden.
Sarah Trees
24

Sie könnten versuchen, Folgendes zu verwenden:

Sie müssen sich überhaupt nicht mit HTML-Elementen befassen.

var data = {
    key: 'value'
};
var fileName = 'myData.json';

// Create a blob of the data
var fileToSave = new Blob([JSON.stringify(data)], {
    type: 'application/json',
    name: fileName
});

// Save the file
saveAs(fileToSave, fileName);

Wenn Sie den JSON hübsch drucken möchten, können Sie gemäß dieser Antwort Folgendes verwenden:

JSON.stringify(data,undefined,2)
Gautham
quelle
1
saveAs () ist von FileSaver.js - github.com/eligrey/FileSaver.js
Gautham
1
"Keine Notwendigkeit, sich mit irgendwelchen HTML-Elementen zu befassen" ... und den Quellcode von filesaver.js zu lesen ... es macht genau das lol
War
1
Ja. Ich wollte damit sagen, dass man sich nicht direkt mit den HTML-Elementen befassen muss.
Gautham
3
Dies ist die beste Antwort, da es keine
Größenbeschränkung von
für FileSaver ref hochgestimmt ref. perfekt funktionieren.
Niemand
15

Folgendes hat bei mir funktioniert:

/* function to save JSON to file from browser
* adapted from http://bgrins.github.io/devtools-snippets/#console-save
* @param {Object} data -- json object to save
* @param {String} file -- file name to save to 
*/
function saveJSON(data, filename){

    if(!data) {
        console.error('No data')
        return;
    }

    if(!filename) filename = 'console.json'

    if(typeof data === "object"){
        data = JSON.stringify(data, undefined, 4)
    }

    var blob = new Blob([data], {type: 'text/json'}),
        e    = document.createEvent('MouseEvents'),
        a    = document.createElement('a')

    a.download = filename
    a.href = window.URL.createObjectURL(blob)
    a.dataset.downloadurl =  ['text/json', a.download, a.href].join(':')
    e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
    a.dispatchEvent(e)
}

und dann so zu nennen

saveJSON(myJsonObject, "saved_data.json");
maia
quelle
3
Dies ist zwar eine gute Antwort, initMouseEvent()aber ein veralteter Webstandard und sollte nicht mehr verwendet werden. Verwenden Sie stattdessen die new MouseEvent()Schnittstelle. Es ist jedoch nur ein kleiner Refaktor.
Morkro
10

Ich musste kürzlich eine Schaltfläche erstellen, mit der eine JSON-Datei mit allen Werten eines großen Formulars heruntergeladen werden konnte. Ich brauchte dies, um mit IE / Edge / Chrome zu arbeiten. Das habe ich getan:

function download(text, name, type)
    {
        var file = new Blob([text], {type: type});
        var isIE = /*@cc_on!@*/false || !!document.documentMode;
        if (isIE)
        {
            window.navigator.msSaveOrOpenBlob(file, name);
        }
        else
        {
            var a = document.createElement('a');
            a.href = URL.createObjectURL(file);
            a.download = name;
            a.click();
        }
     }

download(jsonData, 'Form_Data_.json','application/json');

Es gab ein Problem mit Dateiname und Erweiterung in Edge, aber zum Zeitpunkt des Schreibens schien dies ein Fehler mit Edge zu sein, der behoben werden soll.

Hoffe das hilft jemandem

Brad
quelle
Dies funktionierte unter Chrome, scheint aber unter Firefox nicht zu funktionieren ... bitte helfen Sie! codepen.io/anon/pen/ePYPJb
Urmil Parikh
1
Schöne Funktion, hinzufügen document.body.appendChild(a); a.style.display = 'none';, damit es in Firefox funktioniert .
Fabian von Ellerts
5

Einfache, saubere Lösung für diejenigen, die nur auf moderne Browser abzielen:

function downloadTextFile(text, name) {
  const a = document.createElement('a');
  const type = name.split(".").pop();
  a.href = URL.createObjectURL( new Blob([text], { type:`text/${type === "txt" ? "plain" : type}` }) );
  a.download = name;
  a.click();
}

downloadTextFile(JSON.stringify(myObj), 'myObj.json');
user993683
quelle
Danke, nur eine, die mir keine Größenprobleme bereitete
Roelant
4

Die downloadEigenschaft von Links ist neu und wird in Internet Explorer nicht unterstützt (siehe Kompatibilitätstabelle hier ). Eine browserübergreifende Lösung für dieses Problem finden Sie in FileSaver.js

robertjd
quelle
2

Reagieren : Fügen Sie dies an der gewünschten Stelle in Ihre Rendermethode ein.

• Objekt im Status :

<a
  className="pull-right btn btn-primary"
  style={{ margin: 10 }}
  href={`data:text/json;charset=utf-8,${encodeURIComponent(
  JSON.stringify(this.state.objectToDownload)
  )}`}
  download="data.json"
>
  DOWNLOAD DATA AS JSON
</a>

• Objekt in Requisiten :

<a
  className="pull-right btn btn-primary"
  style={{ margin: 10 }}
  href={`data:text/json;charset=utf-8,${encodeURIComponent(
  JSON.stringify(this.props.objectToDownload)
  )}`}
  download="data.json"
>
  DOWNLOAD DATA AS JSON
</a>

Klassenname und Stil sind optional. Ändern Sie den Stil entsprechend Ihren Anforderungen.

Abido
quelle
1

Versuchen Sie, einen anderen MIME-Typ festzulegen: exportData = 'data:application/octet-stream;charset=utf-8,';

Es können jedoch Probleme mit dem Dateinamen im Dialogfeld "Speichern" auftreten.

Minimulin
quelle
Entschuldigen Sie, dass Sie zu spät zurückkommen. Ich habe versucht, Ihre Antwort und es Download-Datei, aber enthält falsche Daten darin .. :(
Eugene Yu
1
Das hat bei mir funktioniert ... data = "data:application/octet-stream;charset=utf-8," + encodeURIComponent(JSON.stringify(data)); window.open(data); es lädt die Datei einfach als "Download" herunter, aber die Daten, die ich stringifiziert und dann uri-codiert habe, sind so, wie sie sein sollten.
Jason Wiener
0

Wenn Sie ein Konsolen-Snippet (Raser) anstelle eines Dateinamens bevorzugen, können Sie dies tun:

window.open(URL.createObjectURL(
    new Blob([JSON.stringify(JSON)], {
      type: 'application/binary'}
    )
))
Zum Beispiel'
quelle