33

I want to download binary files using Javascript.

I have a REST service that returns the binary data and i want to know if its possible to show the binary file, whichever the file extension.

This is my current code:

var xhr = new XMLHttpRequest;
xhr.open("GET", requestUrl);
xhr.addEventListener("load", function () {
    var ret = [];
    var len = this.responseText.length;
    var byte;
    for (var i = 0; i < len; i++) {
        byte = (this.responseText.charCodeAt(i) & 0xFF) >>> 0;
        ret.push(String.fromCharCode(byte));
    }
    var data = ret.join('');
    data = "data:application/pdf;base64," + btoa(data);

    window.open(data, '_blank', 'resizable, width=1020,height=600');
}, false);

xhr.setRequestHeader("Authorization", "Bearer " + client.accessToken);
xhr.overrideMimeType("octet-stream; charset=x-user-defined;");
xhr.send(null);

Thanks!

nuno.filipesf
  • 755
  • 1
  • 9
  • 18

1 Answers1

64

Have a look at the MDN article on XMLHttpRequest.

If you set the response of the XMLHttpRequest to ArrayBuffer you could do the following:

var xhr = new XMLHttpRequest();
xhr.open("GET", requestUrl);
xhr.responseType = "arraybuffer";

xhr.onload = function () {
    if (this.status === 200) {
        var blob = new Blob([xhr.response], {type: "application/pdf"});
        var objectUrl = URL.createObjectURL(blob);
        window.open(objectUrl);
    }
};
xhr.send();

Option 2:
You could use Blob as the response of the XMLHttpRequest. And then maybe save it in the FileSystem (FileSystem API)

It may look like:

var xhr = new XMLHttpRequest();
xhr.open("GET", requestUrl);
xhr.responseType = "blob";

xhr.onload = function () {
    onDownloaded(this);
};
xhr.send();

Option 3:
If you only want to download and "show" images you can easily do this like so:

var img = new Image();

// add the onload event before setting the src
img.onload = function() {
    onImageDownloaded(img);
}

// start the download by setting the src property
img.src = requestUrl
Jo David
  • 1,696
  • 2
  • 18
  • 20
  • Thanks for the answer. But my problem is a bit different. I can download pdfs or images, but when i call the REST service that returns the binary data, i don't know what is the type of the file. – nuno.filipesf Jul 17 '13 at 10:25
  • 1
    You could make another request just before downloading the file to get the fileType and maybe the file name (for the UI). – Jo David Jul 17 '13 at 11:05
  • 1
    why would you not use content-type header instead of hard coding type as application/pdf? – Akash Kava Sep 09 '14 at 13:12
  • 1
    A tiny correction Jo, for a bytearray Brob parameter should be an array. ...new Blob([xhr.response], {type: 'application/pdf'}); – Maxim Aug 02 '16 at 16:57
  • @Maxim this answer is 3 years old. It might have changed in that time :) At the time of writing it, it worked that way (iirc). – Jo David Aug 03 '16 at 08:03
  • @JoDavid Sorry, I don't like when someone's recapping my very old answers. Though, after long search I found yours and it helped to solve an issue for me it might help someone else too, just that little thing which I found in mozilla doc that you added a link to. – Maxim Aug 03 '16 at 13:49
  • 2
    Where the function `onDownloaded` is defined? – Arup Rakshit Aug 30 '18 at 13:12
  • Thank you for `xhr.responseType = "blob";`! – Alex Feb 10 '20 at 09:29
  • Should we revoke objectUrl? – Miki Nov 09 '22 at 13:02