How to set a header for a HTTP GET request, and trigger file download? How to set a header for a HTTP GET request, and trigger file download? ajax ajax

How to set a header for a HTTP GET request, and trigger file download?


There are two ways to download a file where the HTTP request requires that a header be set.

The credit for the first goes to @guest271314, and credit for the second goes to @dandavis.

The first method is to use the HTML5 File API to create a temporary local file,and the second is to use base64 encoding in conjunction with a data URI.

The solution I used in my project uses the base64 encoding approach for small files, or when the File API is not available,otherwise using the the File API approach.

Solution:

        var id = 123;        var req = ic.ajax.raw({            type: 'GET',            url: '/api/dowloads/'+id,            beforeSend: function (request) {                request.setRequestHeader('token', 'token for '+id);            },            processData: false        });        var maxSizeForBase64 = 1048576; //1024 * 1024        req.then(            function resolve(result) {                var str = result.response;                var anchor = $('.vcard-hyperlink');                var windowUrl = window.URL || window.webkitURL;                if (str.length > maxSizeForBase64 && typeof windowUrl.createObjectURL === 'function') {                    var blob = new Blob([result.response], { type: 'text/bin' });                    var url = windowUrl.createObjectURL(blob);                    anchor.prop('href', url);                    anchor.prop('download', id+'.bin');                    anchor.get(0).click();                    windowUrl.revokeObjectURL(url);                }                else {                    //use base64 encoding when less than set limit or file API is not available                    anchor.attr({                        href: 'data:text/plain;base64,'+FormatUtils.utf8toBase64(result.response),                        download: id+'.bin',                    });                    anchor.get(0).click();                }            }.bind(this),            function reject(err) {                console.log(err);            }        );

Note that I'm not using a raw XMLHttpRequest,and instead using ic-ajax,and should be quite similar to a jQuery.ajax solution.

Note also that you should substitute text/bin and .bin with whatever corresponds to the file type being downloaded.

The implementation of FormatUtils.utf8toBase64can be found here


Try

html

<!-- placeholder ,     `click` download , `.remove()` options ,     at js callback , following js --><a>download</a>

js

        $(document).ready(function () {            $.ajax({                // `url`                 url: '/echo/json/',                type: "POST",                dataType: 'json',                // `file`, data-uri, base64                data: {                    json: JSON.stringify({                        "file": "data:text/plain;base64,YWJj"                    })                },                // `custom header`                headers: {                    "x-custom-header": 123                },                beforeSend: function (jqxhr) {                    console.log(this.headers);                    alert("custom headers" + JSON.stringify(this.headers));                },                success: function (data) {                    // `file download`                    $("a")                        .attr({                        "href": data.file,                            "download": "file.txt"                    })                        .html($("a").attr("download"))                        .get(0).click();                    console.log(JSON.parse(JSON.stringify(data)));                },                error: function (jqxhr, textStatus, errorThrown) {                  console.log(textStatus, errorThrown)                }            });        });

jsfiddle http://jsfiddle.net/guest271314/SJYy3/


I'm adding another option. The answers above were very useful for me, but I wanted to use jQuery instead of ic-ajax (it seems to have a dependency with Ember when I tried to install through bower). Keep in mind that this solution only works on modern browsers.

In order to implement this on jQuery I used jQuery BinaryTransport. This is a nice plugin to read AJAX responses in binary format.

Then you can do this to download the file and send the headers:

$.ajax({    url: url,    type: 'GET',    dataType: 'binary',    headers: headers,    processData: false,    success: function(blob) {        var windowUrl = window.URL || window.webkitURL;        var url = windowUrl.createObjectURL(blob);        anchor.prop('href', url);        anchor.prop('download', fileName);        anchor.get(0).click();        windowUrl.revokeObjectURL(url);    }});

The vars in the above script mean:

  • url: the URL of the file
  • headers: a Javascript object with the headers to send
  • fileName: the filename the user will see when downloading the file
  • anchor: it is a DOM element that is needed to simulate the download that must be wrapped with jQuery in this case. For example $('a.download-link').