0

I have a JavaScript Pivot table that displays data to the user. The user can select the columns/rows etc. I've added an export to Excel button, that performs an ajax post with the current data/view of the pivot table (json data). It posts the data to my server that converts that to an Excel file.

Creating the file all works well, but my problem is getting the file to the user. From what I've read I can't send a file to a user after an ajax post.

I'm happy to use a plain html post (in fact it is what I want since I can redirect the user to the file), but I don't know how to include the pivot table data as part of the post since it is not a form.

I know I can save the file locally and send a url back but this complicates things and I would like to avoid it.

Is it possible to do this without saving the file locally and sending a url where the file is located?

Kritz
  • 7,099
  • 12
  • 43
  • 73
  • "Creating the file all works well, but my problem is getting the file to the user" By "getting the file to the user" I assume you mean getting the file to the browser? If so, after saving the file to your server you should have a url link to that file right? – Zuks Jan 19 '17 at 12:54
  • `I can't send a file to a user after an ajax post` Yes you can http://stackoverflow.com/a/20830337 – Vinay Jan 19 '17 at 12:55
  • No, I don't have a url link. I create the file in memory – Kritz Jan 19 '17 at 13:00
  • @novice in the method you suggested it does not send any post data to the server – Kritz Jan 19 '17 at 13:11

1 Answers1

1

Browsers don't (yet) support JSON serialization of forms, so AFAIK it's not really possible to send JSON to backend using pure forms.

I have two solutions that will not require saving file on the server:

1) Simple solution would be to generate an invisible form with JavaScript, create hidden input of name json and populate it with JSON content to send to the server. On the server side, you would read the form data and parse JSON that is stored in the data. Then you just generate the file and send the file in response. The browser should trigger download dialog.

var form = document.createElement('form');
form.method = 'post';
form.action = 'url';
var input = document.createElement('input');
input.type = 'hidden';
textarea.name = 'json';
textarea.value = JSON.stringify(your_json);
form.appendChild(input);
document.body.appendChild(form);
form.submit();
form.parentNode.removeChild(form);

2) Second option uses ajax to send data to the server. The browsers need to support several APIs, though.

You do your JSON request as usual and the server should respond with header Content-Type: here-the-MIME-type-of-your-file and with the file contents in response body.

The code on client side should look like:

var json = JSON.stringify({here: ['your', 'json', 'to', 'send', 'to', 'server']});
var xhr = new XMLHttpRequest();
xhr.open('POST', '/your/api/url', true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.responseType = 'arraybuffer';
xhr.addEventListener('load', function () {
  var blob = new Blob([this.response], { // reading response, not responseText
    type: this.getResponseHeader('Content-Type')
  });

  var url = URL.createObjectURL(blob);
  var a = document.createElement('a');
  a.href = url;
  a.download = 'file_name.txt'; // set proper extension
  document.body.appendChild(a); // it needs to be added to the document in order to work
  a.click();
  a.parentNode.removeChild(a);
});

xhr.send(json);

Also, the created URL objects should be revoked at some point, otherwise they will exist until the page reloads. But I think they cannot be revoked before the user downloads the file. So it's one task still to do with the above code.

Rafael
  • 18,349
  • 5
  • 58
  • 67
  • I think in options 2 text area should be input. Other than that it worked perfectly! Thanks again – Kritz Jan 19 '17 at 19:17