27

I use this code to download excel file from server.

$.ajax({ headers: CLIENT.authorize(), url: '/server/url', type: 'POST', contentType: "application/json; charset=utf-8", data: JSON.stringify(jsonData), success: function (data) { alert('Data size: ' + data.length); var blob = new Blob([data], { type: "application/vnd.ms-excel" }); alert('BLOB SIZE: ' + data.length); var URL = window.URL || window.webkitURL; var downloadUrl = URL.createObjectURL(blob); document.location = downloadUrl; }, }); 

The problem I experience is that even though data and blob sizes are identical, the moment document.location gets assigned I'm prompted to download almoste two times larger excel file. And when I try to open it, excel complains about wrong file format and opened file contains a lot of garbage, even though required text is still there.

Any ideas what is causing this and how to avoid it?

5
  • I dont think that is a great idea. Why not just let the server push the file to the browser for a normal download stream. This seems very unnatural, unless you have a very specific reason to do this, like some kind of Proxy or on-line analysis, but its just going to thrash browser memeory . Commented Apr 1, 2015 at 14:36
  • Try setting the content-type to arrayBuffer Commented Apr 1, 2015 at 14:50
  • @ppumkin, unfortunately I need to meet requirements. I can't store file on server and I need to pass authorization header to get the file. Commented Apr 1, 2015 at 15:00
  • @levi, do you mean content type where I specify JSON or when creating blob? Commented Apr 1, 2015 at 15:03
  • yes. 10morechars..... Commented Apr 1, 2015 at 16:48

1 Answer 1

46

So I solved the problem using AJAX 2. It natively supports binary streams. You can't use jQuery for that, unless you base64 encode everything, apparently.

Working code looks like this:

var xhr = new XMLHttpRequest(); xhr.open('POST', '/le/url', true); xhr.responseType = 'blob'; $.each(SERVER.authorization(), function(k, v) { xhr.setRequestHeader(k, v); }); xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8'); xhr.onload = function(e) { preloader.modal('hide'); if (this.status == 200) { var blob = new Blob([this.response], {type: 'application/vnd.ms-excel'}); var downloadUrl = URL.createObjectURL(blob); var a = document.createElement("a"); a.href = downloadUrl; a.download = "data.xls"; document.body.appendChild(a); a.click(); } else { alert('Unable to download excel.') } }; xhr.send(JSON.stringify(jsonData)); 

Hope this helps.

Sign up to request clarification or add additional context in comments.

6 Comments

works for chrome/ff. For IE, use msSaveOrOpenBlob stackoverflow.com/questions/24007073/…
This works.. I have tested on Chrome.. on Safari it doesn't :(
+1 for [this.response] how to get blob actually , i was trying like this window.URL.createObjectURL(xhttp.response)
Thank you! Shocking that this is not very simple. Seems like it would be common thing, but took me forever to find this.
note that you must add to body for it to work on Firefox. In the answer: document.body.appendChild(a)...in my code i put document.body && document.body.appendChild(link);
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.