Update 20140702:
(but I'm marking one of the other answers as accepted instead of my own, as it got me halfway there, and to reward the effort)
It appears that setting a HTTP request header is not possible through links with <a href="...">
, and can only be done using XMLHttpRequest
.
However, the URL linked to is a file that should be downloaded (browser should not navigate to its URL), and I am not sure is this can be done using AJAX.
Additionally, the file being returned is a binary file, and AJAX is not intended for that.
How would one go about triggering a file download with a HTTP request that has a custom header added to it?
edit: fix broken link
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.utf8toBase64
can 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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With