0

I want to dynamically create a JSON file in my JS code and also invoke the download of that file?

Any chance I can do that in JavaScript?

THANKS!!

Nik
  • 2,863
  • 6
  • 24
  • 29
  • What do you mean by invoke the download? If you want to place a cookie on the clients machine then yes you can do that. If you want to place it just somewhere on their file system, then no you cannot do that. If you want to create the JSON, stringify it, output it, let the client select and save it, then yes you can do that. – recneps Jun 04 '13 at 06:42
  • Thanks for your quick answer. Ok I want the user to select and save the JSON file on his file system. Any chance?! – Nik Jun 04 '13 at 06:45
  • Sorry, that cannot be done with JavaScript alone. like Tom is saying, you would need some server side scripting. – recneps Jun 04 '13 at 06:49
  • Actually Data URIs can be used to automatically download generated files without any server side... – Tom Jun 04 '13 at 06:51

2 Answers2

1

Either use a server side language and GET vars (don't forget to set the MIME type to something like application/octet-stream) or base64 encode the JSON into a Data URI if you aren't worried about supporting legacy browsers.

Here's an example; try writing some text and then pressing download. Only problem is you can't control the filename:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Data URI</title>
    <script>
      var Base64 = {

  // private property
  _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

  // public method for encoding
  encode : function (input) {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    input = Base64._utf8_encode(input);

    while (i < input.length) {

      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }

      output = output +
      this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
      this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

    }

    return output;
  },

  // public method for decoding
  decode : function (input) {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {

      enc1 = this._keyStr.indexOf(input.charAt(i++));
      enc2 = this._keyStr.indexOf(input.charAt(i++));
      enc3 = this._keyStr.indexOf(input.charAt(i++));
      enc4 = this._keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }

    }

    output = Base64._utf8_decode(output);

    return output;

  },

  // private method for UTF-8 encoding
  _utf8_encode : function (string) {
    string = string.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < string.length; n++) {

      var c = string.charCodeAt(n);

      if (c < 128) {
        utftext += String.fromCharCode(c);
      }
      else if((c > 127) && (c < 2048)) {
        utftext += String.fromCharCode((c >> 6) | 192);
        utftext += String.fromCharCode((c & 63) | 128);
      }
      else {
        utftext += String.fromCharCode((c >> 12) | 224);
        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
        utftext += String.fromCharCode((c & 63) | 128);
      }

    }

    return utftext;
  },

  // private method for UTF-8 decoding
  _utf8_decode : function (utftext) {
    var string = "";
    var i = 0;
    var c = c1 = c2 = 0;

    while ( i < utftext.length ) {

      c = utftext.charCodeAt(i);

      if (c < 128) {
        string += String.fromCharCode(c);
        i++;
      }
      else if((c > 191) && (c < 224)) {
        c2 = utftext.charCodeAt(i+1);
        string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
        i += 2;
      }
      else {
        c2 = utftext.charCodeAt(i+1);
        c3 = utftext.charCodeAt(i+2);
        string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
        i += 3;
      }

    }

    return string;
  }

}
      window.onload=function(){
        document.getElementById('download').onclick=function(){
          window.open("data:application/octet-stream;base64,"+Base64.encode(document.getElementById('text').value));
        }
      }
    </script>
  </head>
  <body style="margin:0;padding:0;overflow:hidden;">
    <textarea id="text"></textarea>
    <input type="button" value="Download" style="height:auto;width:100px" id="download"/>
  </body>
</html>
Tom
  • 4,422
  • 3
  • 24
  • 36
0

Yes you can, but you need to create this file as a string. Then, call:

window.location = window.URL.createObjectURL(new Blob([what_is_in_your_file], {type: "application/json"}));
ecstrema
  • 543
  • 1
  • 5
  • 20